用C语言完成 ping代码
时间: 2023-06-08 14:08:33 浏览: 136
以下是C语言实现Ping的代码:
```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip_icmp.h>
#include <netdb.h>
#include <arpa/inet.h>
#define PACKET_SIZE 4096
#define MAX_WAIT_TIME 5
#define MAX_NO_PACKETS 4
struct packet
{
struct icmphdr hdr;
char msg[PACKET_SIZE-sizeof(struct icmphdr)];
};
static char recv_packet[PACKET_SIZE];
static char send_packet[PACKET_SIZE];
static int sockfd;
static int packets_sent = 0;
static int packets_received = 0;
static struct sockaddr_in dest_addr;
static struct sockaddr_in from_addr;
static struct timeval start_time;
static unsigned short get_checksum(unsigned short *ptr, int nbytes)
{
unsigned long sum;
for (sum=0; nbytes>1; nbytes-=2)
sum += *ptr++;
if (nbytes==1)
sum += *(unsigned char *)ptr;
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
return (unsigned short)(~sum);
}
static void send_packet_signal(int signo)
{
struct packet *pkt = (struct packet *)send_packet;
gettimeofday(&pkt->hdr.timestamp, NULL);
pkt->hdr.type = ICMP_ECHO;
pkt->hdr.code = 0;
pkt->hdr.un.echo.id = getpid();
++packets_sent;
pkt->hdr.un.echo.sequence = packets_sent;
memset(pkt->msg, 0xa5, sizeof(pkt->msg));
pkt->hdr.checksum = get_checksum((unsigned short *)pkt, sizeof(struct packet));
sendto(sockfd, pkt, sizeof(*pkt), 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
}
int ping(const char *ip_addr)
{
struct hostent *host;
struct icmp *icmp;
struct timeval tv;
struct sigaction sa;
int n;
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (sockfd < 0)
{
perror("socket");
return -1;
}
dest_addr.sin_family = AF_INET;
dest_addr.sin_addr.s_addr = inet_addr(ip_addr);
icmp = (struct icmp *)send_packet;
icmp->icmp_type = ICMP_ECHO;
icmp->icmp_code = 0;
icmp->icmp_id = getpid();
icmp->icmp_seq = 1;
memset(&icmp->icmp_data, 0xa5, sizeof(icmp->icmp_data));
gettimeofday(&icmp->icmp_rtime, NULL);
icmp->icmp_cksum = get_checksum((unsigned short *)icmp, sizeof(*icmp));
if ((host = gethostbyname(ip_addr)) == NULL)
return -2;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = send_packet_signal;
if (sigaction(SIGALRM, &sa, NULL) < 0)
{
perror("sigaction");
return -3;
}
packets_sent = packets_received = 0;
while (packets_sent < MAX_NO_PACKETS)
{
tv.tv_sec = MAX_WAIT_TIME;
tv.tv_usec = 0;
alarm(MAX_WAIT_TIME);
n = recvfrom(sockfd, recv_packet, sizeof(recv_packet), 0, (struct sockaddr *)&from_addr, (socklen_t *)sizeof(from_addr));
if (n < 0 && errno == EINTR)
continue;
else if (n < 0)
{
perror("recvfrom");
return -4;
}
gettimeofday(&tv, NULL);
memcpy(&icmp->icmp_rtime, &tv, sizeof(tv));
if (icmp->icmp_type == ICMP_ECHOREPLY)
++packets_received;
}
close(sockfd);
return 0;
}
int main(int argc, char *argv[])
{
if (argc < 2)
{
printf("Usage: %s IP\n", argv[0]);
return -1;
}
if (ping(argv[1]) != 0)
printf("Ping failed.\n");
else
printf("Ping succeeded.\n");
return 0;
}
```
该代码通过ICMP协议实现了Ping功能,使用该函数需要传入一个字符串类型的IP地址作为参数。函数返回值为0表示Ping成功,否则表示Ping失败。
阅读全文