linux ping 源代码
时间: 2023-09-12 20:00:41 浏览: 531
Linux中的“ping”命令是一个常用的网络工具,它用于测试与目标主机之间的连接以及测量往返延迟(RTT)。
“ping”命令的源代码可以在Linux内核代码中找到。在Linux内核源代码中的`net/ipv4/icmp.c`和`include/net/icmp.h`两个文件中实现了“ping”命令的主要功能。
源代码中的主要函数是`icmp_rcv()`、`icmp_send()`和`ping_v4_sendmsg()`。
`icmp_rcv()`函数用于处理接收到的ICMP(Internet控制消息协议)报文。它会检查报文类型是否是回显请求(Echo Request),如果是,就调用`icmp_send()`函数发送回显回答(Echo Reply)报文。
`icmp_send()`函数用于发送回答报文。它通过调用`ping_v4_sendmsg()`函数构建并发送ICMP报文。
`ping_v4_sendmsg()`函数用于构建并发送ICMP报文。它会设置目标地址、报文类型、标识符和顺序号,并计算校验和。
整个过程中,Linux使用Internet协议栈层来处理网络报文的接收和发送。其中,IP层负责将报文封装为IP数据包,并根据目标地址选择相应的发送接口或路由。ICMP是IP协议的一个扩展,在与目标主机通信时,会通过构建ICMP报文来实现“ping”命令的功能。
总的来说,Linux中“ping”命令的源代码通过ICMP协议实现了与目标主机的连接测试和往返延迟的测量。它基于Linux内核中与网络通信相关的函数来进行报文的发送和接收。
相关问题
linux ping 源代码下载
Linux操作系统是开放源代码的操作系统,包含了许多开源软件。其中,ping命令就是Linux操作系统中用于检测网络连接性的工具。用户可以通过下载ping命令的源代码来了解其具体实现过程和相关配置参数。
要下载Linux ping源代码,首先需要在Linux系统中安装git客户端。然后在终端中输入以下命令:
git clone https://github.com/iputils/iputils.git
这个命令会从源代码仓库中下载ping命令的所有源代码和相关文件。下载完成后,用户可以打开源代码文件夹,在其中找到ping.c文件,这个文件就是ping命令的核心代码。
用户可以通过阅读ping.c文件了解其中的具体实现过程,理解ping命令的工作原理。在实际使用中,用户也可以根据需要修改ping命令的代码,添加新的功能或者定制特定的网络检测需求。
除了ping命令之外,Linux操作系统中还有许多其他开源软件可以供用户自由下载和修改。这些开源软件不仅方便用户进行二次开发,也促进了开源社区的发展。
linux ping源码
以下是 Linux 中 ping 命令的源代码(基于 Ubuntu 20.04 LTS 版本):
```
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <signal.h>
#include <errno.h>
#define PACKET_SIZE 4096
char sendpacket[PACKET_SIZE];
char recvpacket[PACKET_SIZE];
int sockfd, datalen = 56;
int nsend = 0, nreceived = 0;
struct sockaddr_in dest_addr;
pid_t pid;
struct timeval tvrecv;
void statistics(int signo)
{
printf("\n%d packets transmitted, %d received , %%%d lost\n",
nsend, nreceived, (nsend - nreceived) / nsend * 100);
close(sockfd);
exit(1);
}
unsigned short cal_chksum(unsigned short *addr, int len)
{
int nleft = len;
int sum = 0;
unsigned short *w = addr;
unsigned short answer = 0;
while (nleft > 1) {
sum += *w++;
nleft -= 2;
}
if (nleft == 1) {
*(unsigned char *)(&answer) = *(unsigned char *)w;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return answer;
}
void send_packet(void)
{
nsend++;
struct icmp *icmp = (struct icmp *)sendpacket;
icmp->icmp_type = ICMP_ECHO;
icmp->icmp_code = 0;
icmp->icmp_cksum = 0;
icmp->icmp_seq = nsend;
icmp->icmp_id = pid;
memset(icmp->icmp_data, 0xa5, datalen);
gettimeofday((struct timeval *)icmp->icmp_data, NULL);
icmp->icmp_cksum = cal_chksum((unsigned short *)icmp, datalen + 8);
sendto(sockfd, sendpacket, datalen + 8, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
}
void recv_packet(void)
{
int n;
extern int errno;
signal(SIGALRM, statistics);
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
fd_set readfd;
while (nreceived < nsend) {
FD_ZERO(&readfd);
FD_SET(sockfd, &readfd);
int ret = select(sockfd+1, &readfd, NULL, NULL, &timeout);
if (ret == -1) {
if (errno == EINTR) {
continue;
}
perror("select error");
return;
} else if (ret == 0) {
printf("request timeout\n");
continue;
}
if (FD_ISSET(sockfd, &readfd)) {
n = recvfrom(sockfd, recvpacket, sizeof(recvpacket), 0, NULL, NULL);
if (n < 0) {
if (errno == EINTR) {
continue;
}
perror("recvfrom error");
return;
}
gettimeofday(&tvrecv, NULL);
struct ip *ip = (struct ip *)recvpacket;
struct icmp *icmp = (struct icmp *)(recvpacket + (ip->ip_hl << 2));
int len = n - (ip->ip_hl << 2);
if (icmp->icmp_type == ICMP_ECHOREPLY && icmp->icmp_id == pid) {
nreceived++;
printf("%d bytes from %s: icmp_seq=%u ttl=%d time=%.1f ms\n",
len, inet_ntoa(ip->ip_src), icmp->icmp_seq, ip->ip_ttl,
(tvrecv.tv_sec - ((struct timeval *)icmp->icmp_data)->tv_sec) * 1000.0 +
(tvrecv.tv_usec - ((struct timeval *)icmp->icmp_data)->tv_usec) / 1000.0);
} else {
printf("received icmp packet with type %d code %d\n", icmp->icmp_type, icmp->icmp_code);
}
}
}
}
int main(int argc, char *argv[])
{
if (argc != 2) {
printf("Usage: ping <ip address>\n");
return 1;
}
struct hostent *host = gethostbyname(argv[1]);
if (host == NULL) {
perror("gethostbyname error");
return 1;
}
pid = getpid();
printf("PING %s (%s) %d bytes of data.\n", host->h_name, inet_ntoa(*(struct in_addr *)host->h_addr), datalen);
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (sockfd < 0) {
perror("socket error");
return 1;
}
setuid(getuid());
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
bzero(&dest_addr, sizeof(dest_addr));
dest_addr.sin_family = AF_INET;
memcpy(&dest_addr.sin_addr, host->h_addr, host->h_length);
signal(SIGINT, statistics);
while (1) {
send_packet();
recv_packet();
sleep(1);
}
return 0;
}
```
这段代码实现了 ping 命令的功能。它使用 ICMP 协议发送和接收数据包,计算往返时间并输出结果。其中 `send_packet()` 函数用于发送 ICMP 请求数据包,`recv_packet()` 函数用于接收 ICMP 响应数据包,`statistics()` 函数用于统计传输结果。
阅读全文