深入探究Linux Ping源码,看清网络通信内部机理(linuxping源码)
Linux Ping 是 Linux 系统上传统的网络测试工具,常用于网络上主机的存活检测,某些功能如在线网络测试;它是通过协议 ICMP 来实现它的网络测试和管理,当 ping 命令发出之后,远程主机就会收到一个 ICMP 协议的信息,ICMP 会回传消息给本机,根据传回来的消息就能够获知到网络的通断。Ping 技术内部的机制在做网络测试时很重要,此外,对于深入探究 Linux 的 Ping 源码,也有助于了解深入ICMP 消息以及网络的交互机制。
Linux 中的 Ping 源码分为三部分完成,第一部分是组装 ICMP 消息发给远程主机,第二部分是等待远程主机的回应,第三部分是分析收到 ICMP 回应消息,更深入地探究 Linux Ping 源码需要掌握它关键的 C 语言编程技术:sockaddr_in/sockaddr,sendto/recvfrom,gethostbyname/gethostbyaddr 以及 IP_HDRINCL。
Linux Ping 源码文件以全局变量的形式声明,并初始化:
“`c
char snd_packet [PACKET_SIZE],
rcv_packet[PACKET_SIZE];
struct sockaddr_in dstaddr;
socklen_t addr_len;
struct sockaddr_in from;
struct icmp *icmp_hdr;
struct ip *ip_hdr;
接下来在 main 程序中,首先创建 socket,然后填写设置目标地址:
```c// 创建套接字
int sockfd; if ((sockfd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP))
{ perror ("socket error");
exit (1); }
// 将要发送到目标地址
memset (&dstaddr, 0, sizeof (struct sockaddr_in)); dstaddr.sin_family = AF_INET;
dstaddr.sin_addr = dst;
之后就是设置 IP 首部信息和 ICMP 消息:
“`c
// 设置 IP 首部信息( IP_HDRINCL 会让内核不填充 IP 首部)
if (setsockopt (sockfd, IPPROTO_IP, IP_HDRINCL, &opt, sizeof (opt))
{
perror (“setsockopt error”);
exit (1);
}
// 设置 ICMP 消息
icmp_hdr = (struct icmp*) snd_packet;
icmp_hdr->type = ICMP_ECHO;
icmp_hdr->code = 0;
icmp_hdr->un.echo.id = getpid ();
icmp_hdr->un.echo.sequence = 0;
icmp_hdr->checksum = check_sum((unsigned short*) icmp_hdr, sizeof (struct icmp));
接下来:
```c// 发送 ICMP 消息给目标地址
if ((sendto (sockfd, snd_packet, sizeof (snd_packet), 0, (struct sockaddr*) &dstaddr, sizeof (struct sockaddr_in))) {
perror ("sendto error"); exit (1);
}
最后,接收 ICMP 消息并处理:
“`c
// 接收 ICMP 消息
addr_len = sizeof (struct sockaddr_in);
if (recvfrom (sockfd, rcv_packet, sizeof (rcv_packet), 0, (struct sockaddr*) &from, &addr_len)
{
perror (“recvfrom error”);
exit (1);
}
// 根据接收到的 ICMP 消息,判断情况
if (icmp_hdr->type == ICMP_ECHOREPLY)
{
printf (“ping ok!\n”);
}
深入探究源码,看清楚了 Linux Ping 工具的内部机制。它使用到了 ICMP 协议,控制网络通信前,先发送 ICMP 请求,再接收 ICMP 响应消息,然后根据 ICMP 响应消息来判断网络连接正常,这样就可以实现Ping 网络测试了。