系列博客参考:http://blog.youkuaiyun.com/zy416548283/article/category/1108400
代码以编号对应放在Github上:https://github.com/zy416548283/networkProgramming
题目
使用原始套接字实现Ping的基本功能,返回序列号、TTL、Time等。
题目解读
- 首先了解Ping这个工具的用法和功能,我们来man一下:
ping uses the ICMP protocol's mandatory ECHO_REQUEST datagram to elicit an ICMP ECHO_RESPONSE from a host or gateway.
ECHO_REQUEST datagrams (``pings'') have an IP and ICMP header, followed by a struct timeval and then an arbitrary number of ``pad'' bytes used to fill out the
packet.
了解原始套接字的用法;
了解ICMP报文的数据结构;
设计实现Ping, 原理部分, 可以参考[TCP/IP 详解 卷一]
实现
在TCP/IP协议栈里一般都实现了Ping的服务器,所以我们这里只需要实现一个客户端即可。发送ICMP请求报文,服务器收到之后会返回ICMP响应报文。
程序的主流程是定时发送ICMP请求报文(定时发送是使用SIGALRM信号驱动),并且在原始套接字上循环接收读入的每个分组;并且需要对命令行参数进行处理。
创建原始套接字如下所示:
sockfd = Socket(pr->sasend->sa_family, SOCK_RAW, pr->icmpproto);
- 调用SIGALRM信号处理函数发送第一个分组,并且调用在一秒后产生下一个信号,这个是异步调用
void
sig_alrm(int signo)
{
(*pr->fsend)();
alarm(1);
return;
}
- 循环接收ICMP消息
for ( ; ; ) {
msg.msg_namelen = pr->salen;
msg.msg_controllen = sizeof(controlbuf);
n = recvmsg(sockfd, &msg, 0);
if (n < 0) {
if (errno == EINTR)
continue;
else
err_sys("recvmsg error");
}
Gettimeofday(&tval,