计算机网络ping的C语言代码
时间: 2023-10-28 20:05:25 浏览: 135
网络ping代码(c语言)
以下是计算机网络中ping的C语言代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <errno.h>
#define PACKET_SIZE 4096
#define TIMEOUT 4
#define MAX_NO_PACKETS 3
unsigned short checksum(void *b, int len)
{
unsigned short *buf = b;
unsigned int sum=0;
unsigned short result;
for ( sum = 0; len > 1; len -= 2 )
sum += *buf++ ;
if ( len == 1 )
sum += *(unsigned char*)buf;
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
result = ~sum;
return result;
}
int pack(int pack_no, char *sendpacket)
{
int i, packsize;
struct icmp *icmp;
struct timeval *tval;
icmp = (struct icmp*)sendpacket;
icmp->icmp_type = ICMP_ECHO;
icmp->icmp_code = 0;
icmp->icmp_cksum = 0;
icmp->icmp_seq = pack_no;
icmp->icmp_id = getpid();
packsize = 8 + 56;
tval = (struct timeval*)icmp->icmp_data;
gettimeofday(tval, NULL);
icmp->icmp_cksum = checksum(sendpacket, packsize);
return packsize;
}
int unpack(char *buf, int len, char *addr)
{
int i, iphdrlen, rtt;
struct ip *ip;
struct icmp *icmp;
struct timeval *tvsend, tvrecv, tvresult;
ip = (struct ip*)buf;
iphdrlen = ip->ip_hl << 2;
icmp = (struct icmp*)(buf + iphdrlen);
len -= iphdrlen;
if ( len < 8 )
{
printf("ICMP packets\'s length is less than 8\n");
return -1;
}
if ( (icmp->icmp_type == ICMP_ECHOREPLY) && (icmp->icmp_id == getpid()))
{
tvsend = (struct timeval*)icmp->icmp_data;
gettimeofday(&tvrecv, NULL);
tvresult = tvsub(tvrecv, *tvsend);
rtt = tvresult.tv_sec * 1000 + tvresult.tv_usec / 1000;
printf("%d byte from %s: icmp_seq=%u ttl=%d rtt=%d ms\n", len, addr, icmp->icmp_seq, ip->ip_ttl, rtt);
return 0;
}
else
return -1;
}
struct timeval tvsub(struct timeval timeval1, struct timeval timeval2)
{
struct timeval result;
result.tv_sec = timeval1.tv_sec - timeval2.tv_sec;
result.tv_usec = timeval1.tv_usec - timeval2.tv_usec;
if (result.tv_usec < 0)
{
--result.tv_sec;
result.tv_usec += 1000000;
}
return result;
}
int Ping(char *ipaddress)
{
struct hostent *host;
struct icmp sendicmp;
struct sockaddr_in from;
struct sockaddr_in to;
int from_len = 0;
int sockfd = 0, nsend = 0, nreceived = 0, i = 0, packet_no = 0;
char sendpacket[PACKET_SIZE] = {0};
char recvbuf[PACKET_SIZE] = {0};
memset(&from, 0, sizeof(from));
memset(&to, 0, sizeof(to));
if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
{
perror("socket error");
return -1;
}
setuid(getuid());
bzero(&sendicmp, sizeof(sendicmp));
to.sin_family = AF_INET;
if ( inet_addr(ipaddress) == INADDR_NONE )
{
if ((host = gethostbyname(ipaddress)) == NULL)
{
perror("gethostbyname error");
return -1;
}
memcpy(&to.sin_addr, host->h_addr, host->h_length);
}
else
to.sin_addr.s_addr = inet_addr(ipaddress);
printf("Ping %s ...\n", ipaddress);
for ( i = 0; i < MAX_NO_PACKETS; i++)
{
nsend = pack(packet_no++, sendpacket);
if ( sendto(sockfd, sendpacket, nsend, 0, (struct sockaddr*)&to, sizeof(to)) < 0 )
{
perror("sendto error");
continue;
}
nreceived++;
if ( recvfrom(sockfd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr*)&from, &from_len) < 0 )
{
perror("recvform error");
continue;
}
if ( unpack(recvbuf, sizeof(recvbuf), inet_ntoa(from.sin_addr)) == -1 )
continue;
sleep(1);
}
printf("Ping statistics for %s:\n", ipaddress);
printf("\tPackets: Sent = %d, Received = %d, Lost = %d(%d%% lost)\n", packet_no, nreceived, (packet_no - nreceived), ((packet_no - nreceived) * 100) / packet_no);
close(sockfd);
return 0;
}
int main(int argc, char *argv[])
{
if ( argc < 2 )
{
printf("Usage: %s IP\n", argv[0]);
return -1;
}
Ping(argv[1]);
return 0;
}
```
注意:此代码需要在 Linux 或 Mac 上编译运行,Windows 上需要进行一些修改才能编译运行。
阅读全文