ping命令的一般格式为:
ping [-dfnqrRv][-c 发送次数][-i 间隔秒数][-I 网络界面][-l 前置载入][-p 范本样式][-s 数据包大小][-t 存活数值][主机名或IP地址]
参数说明:
-d 使用Socket的SO_DEBUG功能。
-f 极限检测。大量且快速地送网络封包给一台机器,看它的回应。
-n 只输出数值。
-q 不显示任何传送封包的信息,只显示最后的结果。
-r 忽略普通的Routing Table,直接将数据包送到远端主机上。通常是查看本机的网络接口是否有问题。
-R 记录路由过程。
-v 详细显示指令的执行过程。
-c 数目 在发送指定数目的包后停止。
-i 秒数 设定间隔几秒送一个网络封包给一台机器,预设值是一秒送一次。
-I 网络界面 使用指定的网络界面送出数据包。
-l 前置载入 设置在送出要求信息之前,先行发出的数据包。
-p 范本样式 设置填满数据包的范本样式。
-s 字节数 指定发送的数据字节数,预设值是56,加上8字节的ICMP头,一共是64ICMP数据字节。
-t 存活数值 设置存活数值TTL的大小。
:linux下的ping和windows下的ping稍有区别,linux下ping不会自动终止,需要按ctrl+c终止或者用参数-c指定要求完成的回应次数
linux下测试本机与目标主机连通性的命令是ping,这里主要讲解两个参数 –c 与 – i
其中 –c count 次数,也就是ping的次数
-i interval 间隔 ,每次ping之间的时间空格
介绍一下ping原理
ping程序实现
@头文件common.h定义,包含程序中用到的头文件及公共变量、宏、常量、静态变量定义
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define IP_HEAD_LEN 20
#define ICMP_LEN 8
#define BUFFER_SIZE 50 * 1024
/*
* 原始套接字的描述符,由于需要在信号处理器
* 和主程序中共享,所以定义为外部变量(全局)
*/
int ip_fd;
/*进程号*/
int p_id;
/*packet_len为IP包头和ICMP包头长度之和*/
extern int packet_len;
/*对端地址*/
struct sockaddr_in send_addr;
/*发送应用缓冲区*/
char send_buf[1024];
/*报文序列号*/
extern int sequence;
/*主机名指针*/
struct hostent *host;
/*标识是否已经接收到回文*/
int flag;
@主函数main.c定义
#include "common.h"
main(int argc, char **argv)
{
/*命令是ping host(主机名)|ip_address(ip地址)*/
if(argc != 2)
{
/*命令不正确*/
fprintf(stderr, "usage: ping
exit(1);
}
/*创建使用ICMP的原始套接字,这种套接字只有root才能生成*/
ip_fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if(ip_fd < 0)
{
fprintf(stderr, "raw socket error.n");
exit(1);
}
/*改变进程的用户ID, 回收root权限,设置当前用户权限*/
setuid(getpid());
ping(argv[1]);
}
@ping框架的建立ping.c用于初始化ping相关信息及端口信息
#include "common.h"
/*
*handle_alarm用于定时发送IP数据包
*/
void handle_alarm(int signo)
{
send_ip();
alarm(1);
}
ping(char *argv)
{
struct sigaction act;
act.sa_handler = handle_alarm;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
sigaction(SIGALRM, &act, NULL);
/*获取main的进程id,用于设置ICMP的标志符*/
p_id = getpid();
/*扩大套接字接收缓冲区到50K这样做主要为了减小接收缓冲区溢出的的可能性,若无意中ping一个广播地址或多播地址,将会引来大量应答*/
//setsockopt(ip_fd, SOL_SOCKET, SO_RCVBUF, &BUFFER_SIZE, sizeof(BUFFER_SIZE));
/*只须填写地址信息,不需要指定端口信息,因为原始套接字在传输层之下*/
send_addr.sin_family = AF_INET;
/*判断是主机名还是ip地址*/
if(inet_addr(argv) == INADDR_NONE)
{
/*是主机名*/
if((host = gethostbyname(argv)) == NULL)
{
/*主机名错误*/
perror("get host by name error: unknow host.");
exit(1);
}
memcpy(&send_addr.sin_addr, host->h_addr, host->h_length);
}
else
{
/*是ip地址*/
inet_aton(argv, &send_addr.sin_addr);
}
printf("ping %s(%s) %d(%d) bytes of datan", argv,
inet_ntoa(send_addr.sin_addr), sizeof(struct timeval),
sizeof(struct timeval) + IP_HEAD_LEN + ICMP_LEN);
flag = 0;
/*触发一个SIGALRM信号*/
raise(SIGALRM);
recv_ip();
}
@发送报文send.c,建立ICMP报文并打包为IP数据包,发送
#include "common.h"
int sequence = 0;
int packet_len = IP_HEAD_LEN + ICMP_LEN;
/*
*send_ip用于发送包含ICMP报文的IP数据包
*/
send_ip(void)
{
if(sequence != 0 && !flag)
{
printf("Destination Host Unreachablen");
}
int len;
struct icmphdr *icmp_p;
icmp_p = (struct icmphdr *)send_buf;
/*填写ICMP报文类型*/
icmp_p->type = ICMP_ECHO;
/*填写ICMP报文的代码*/
icmp_p->code = 0;
/*填写ICMP报文的标识符*/
(icmp_p->un).echo.id = p_id;
/*填写ICMP报文的序号,并增加ICMP的序号*/
(icmp_p->un).echo.sequence = sequence ++;
/*记录发送时间*/
gettimeofday((struct timeval*)(icmp_p + 1), NULL);
/*printf("%dn", sizeof(struct icmphdr));
printf("type: %dncode: %dnchecksum: %dnun.echo.id: %dnun.echo.sequence: %dnun.gateway: %dnun.frag.__unused:%d nun.frag.mtu: %dnn", icmp_p->type, icmp_p->code, icmp_p->checksum, (icmp_p->un).echo.id, (icmp_p- >un).echo.sequence, (icmp_p->un).gateway, (icmp_p->un).frag.__unused, (icmp_p->un).frag.mtu);
printf("type: %dncode: %dnchecksum: %dnun.echo.id: %dnun.echo.sequence: %dnun.gateway: %dnun.frag.__unused: %d nun.frag.mtu: %dnn", sizeof(icmp_p->type), sizeof(icmp_p->code), sizeof(icmp_p->checksum), sizeof((icmp_p- >un).echo.id), sizeof((icmp_p->un).echo.sequence), sizeof((icmp_p->un).gateway), sizeof((icmp_p->un).frag.__unused), sizeof((icmp_p->un).frag.mtu));*/
/*报文的长度等于IP包长度加上ICMP报文长度和数据长度*/
len = sizeof(struct timeval) + packet_len;
/*使用IP计算IP包头校验和的计算方法来计算ICMP的校验和*/
icmp_p->checksum = 0;
icmp_p->checksum = ip_checksum((u_short *)icmp_p, len);
/*发送IP数据包*/
if(sendto(ip_fd, send_buf, len, 0, (struct sockaddr*)&send_addr, sizeof(send_addr)) < 0)
{
fprintf(stderr, "send to error.n");
}
}
@数据校验check_sum.c实现网络数据的校验工作
#include "common.h"
unsigned short ip_checksum(unsigned short *pcheck, int check_len)
{
int nleft = check_len;
int sum = 0;
unsigned short *p = pcheck;
unsigned short result = 0;
while(nleft > 1)
{
sum = sum + *p ++;
nleft -= 2;
}
if(nleft == 1)
{
*(unsigned char *)(&result) = *(unsigned char *)p;
sum += result;
}
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
result = sum;
return result;
}
@数据包接收receive.c,接收IP报文并分析,打印相关信息
#include "common.h"
/*
*recv_ip用于接受包含ICMP报文的IP数据包
*/
recv_ip(void)
{
char recv_buf[1024];
int len;
int n;
struct ip *ip_p;
struct timeval *time_now, *time_send;
struct timeval now;
int iphead_len;
int icmp_len;
struct icmphdr *icmp_p;
float delay;
while(1)
{
n = recvfrom(ip_fd, recv_buf, sizeof(recv_buf), 0, NULL, NULL);
if(n < 0)
{
if(errno = EINTR)
continue;
else
{
printf("recvfrom error.n");
continue;
}
}
ip_p = (struct ip*)recv_buf;
/*获取IP包头长度*/
iphead_len = ip_p->ip_hl<<2;
/*获取IP数据包中包含的ICMP报文*/
icmp_p = (struct icmphdr *)(recv_buf + iphead_len);
/*计算ICMP报文长度,它等于接受到的长度减去IP包头的长度*/
icmp_len = n - iphead_len;
if(icmp_len < 8)
{
fprintf(stderr, "error icmp len = %d.n", icmp_len);
}
/*如果ICMP类型相同则输出显示*/
if(icmp_p->type == ICMP_ECHOREPLY)
{
if((icmp_p->un).echo.id != p_id)
return;
if(icmp_len < 16)
printf("icmplen = %d.n", icmp_len);
flag = 1;//表示已经接收到回文;
gettimeofday(&now, NULL);
time_now = &now;
time_send = (struct timeval*)(icmp_p + 1);
if((time_now->tv_usec -= time_send->tv_usec) < 0)
{
time_now->tv_sec --;
time_now->tv_usec += 1000000;
}
time_now->tv_sec -= time_send->tv_sec;
/*计算延时*/
delay = time_now->tv_sec * 1000.0 + time_now->tv_usec / 1000.0;
/*打印接收到的报文相关信息*/
printf("%d(%d) bytes from %s: icmp_seq=%d ttl=%d time=%.3fmsn",
icmp_len, n, inet_ntoa(send_addr.sin_addr), (icmp_p->un).echo.sequence,
ip_p->ip_ttl, delay);
}
}
}
@makefile文件
#小型ping程序
#用c语言编写
#2008年03月30日
cc = gcc
obj = main.o ping.o send.o receive.o check_sum.o
ping:$(obj)
$(cc) $(obj) -o ping
main.o:main.c common.h ping.c
$(cc) -c main.c
ping.o:ping.c common.h receive.c send.c
$(cc) -c ping.c
send.o:send.c common.h check_sum.c
$(cc) -c send.c
receive.o:receive.c common.h
$(cc) -c receive.c
check_sum.o:check_sum.c common.h
$(cc) -c check_sum.c
clean:
rm -f $(obj)
参考文献:《linux网络编程》
林宇 郭凌云 编著
人民邮电出版社出版
进入makefile所在目录
执行make -f makefile
make clean即可
程序运行结果:(平台ubuntu)
lwj@lwj-desktop:~/Desktop/C/myping$ make -f makefile
gcc -c main.c
gcc -c ping.c
gcc -c send.c
gcc -c receive.c
gcc -c check_sum.c
gcc main.o ping.o send.o receive.o check_sum.o -o ping
lwj@lwj-desktop:~/Desktop/C/myping$ make clean
rm -f main.o ping.o send.o receive.o check_sum.o
lwj@lwj-desktop:~/Desktop/C/myping$ sudo ./ping localhost
Password:
ping localhost(127.0.0.1) 8(36) bytes of data
36(56) bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.061ms
36(56) bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.051ms
36(56) bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.039ms
36(56) bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.051ms
36(56) bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.050ms
36(56) bytes from 127.0.0.1: icmp_seq=5 ttl=64 time=0.052ms
36(56) bytes from 127.0.0.1: icmp_seq=6 ttl=64 time=0.051ms
36(56) bytes from 127.0.0.1: icmp_seq=7 ttl=64 time=0.053ms
[2]+ Stopped sudo ./ping localhost
lwj@lwj-desktop:~/Desktop/C/myping$ sudo ./ping 10.3.2.206
ping 10.3.2.206(10.3.2.206) 8(36) bytes of data
36(56) bytes from 10.3.2.206: icmp_seq=0 ttl=64 time=0.233ms
36(56) bytes from 10.3.2.206: icmp_seq=1 ttl=64 time=0.063ms
36(56) bytes from 10.3.2.206: icmp_seq=2 ttl=64 time=0.044ms
36(56) bytes from 10.3.2.206: icmp_seq=3 ttl=64 time=0.054ms
36(56) bytes from 10.3.2.206: icmp_seq=4 ttl=64 time=0.044ms
36(56) bytes from 10.3.2.206: icmp_seq=5 ttl=64 time=0.052ms
36(56) bytes from 10.3.2.206: icmp_seq=6 ttl=64 time=0.058ms
36(56) bytes from 10.3.2.206: icmp_seq=7 ttl=64 time=0.055ms
36(56) bytes from 10.3.2.206: icmp_seq=8 ttl=64 time=0.066ms
36(56) bytes from 10.3.2.206: icmp_seq=9 ttl=64 time=0.053ms
36(56) bytes from 10.3.2.206: icmp_seq=10 ttl=64 time=0.053ms
36(56) bytes from 10.3.2.206: icmp_seq=11 ttl=64 time=0.052ms
[3]+ Stopped sudo ./ping 10.3.2.206
lwj@lwj-desktop:~/Desktop/C/myping$ sudo ./ping 10.3.2.205
ping 10.3.2.205(10.3.2.205) 8(36) bytes of data
荒野乱斗国际版 (BrawlStars)最新版本v56.274
下载一波超人内置修改器菜单版 安卓版v1.0.2
下载敢达决战官方正版 安卓版v6.7.9
下载敢达决战 安卓版v6.7.9
下载继承了一座戏园子无限声望铜钱版 内置菜单最新版v1.7
继承了一座戏园子折相思版是游戏的破解版本,在该版本中为玩家提
山河半世橙光清软金手指版 无限鲜花v3.24
山河半世是一款超级好玩的橙光恋爱游戏,在游戏中玩家们需要扮演
蓬莱手游折相思版 安卓版v1.0.0
蓬莱免广告版是游戏的修改版本,在该版本中为玩家去除了广告,玩
当红影后橙光游戏破解版2025 最新版v1.0
当红影后橙光破解版是一款超级好玩的娱乐圈题材的橙光游戏,在这
忽然成了万人迷清软完结版 无限鲜花版v12.15
忽然成了万人迷破解版是一款非常好玩的男性向橙光游戏,在有一天