ping程序设计与实现jc++代码
时间: 2024-02-25 09:51:29 浏览: 71
以下是一个简单的 ping 程序的 C++ 代码实现:
```c++
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#define PACKET_SIZE 4096
#define MAX_WAIT_TIME 5
#define MAX_NO_PACKETS 3
using namespace std;
struct timeval tvsend, tvrecv;
int sockfd, datalen = 56;
char sendpacket[PACKET_SIZE], recvpacket[PACKET_SIZE];
int nsend = 0, nreceived = 0;
struct sockaddr_in dest_addr, from_addr;
pid_t pid;
void send_packet();
void recv_packet();
void statistics(int signo);
unsigned short cal_chksum(unsigned short *addr, int len);
int main(int argc, char *argv[])
{
struct hostent *host;
struct protoent *protocol;
if (argc < 2) {
cerr << "usage: " << argv[0] << " <hostname>" << endl;
return 1;
}
if ((protocol = getprotobyname("icmp")) == NULL) {
cerr << "getprotobyname() error" << endl;
return 1;
}
if ((sockfd = socket(AF_INET, SOCK_RAW, protocol->p_proto)) < 0) {
cerr << "socket() error" << endl;
return 1;
}
pid = getpid();
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.sin_family = AF_INET;
if ((host = gethostbyname(argv[1])) == NULL) {
cerr << "gethostbyname() error" << endl;
return 1;
}
memcpy(&dest_addr.sin_addr, host->h_addr, host->h_length);
printf("PING %s (%s) %d bytes of data.\n", argv[1], inet_ntoa(dest_addr.sin_addr), datalen);
memset(sendpacket, 0, sizeof(sendpacket));
memset(recvpacket, 0, sizeof(recvpacket));
signal(SIGALRM, statistics);
while (nsend < MAX_NO_PACKETS) {
nsend++;
send_packet();
recv_packet();
sleep(1);
}
close(sockfd);
return 0;
}
void send_packet()
{
int len;
struct timeval tv;
gettimeofday(&tvsend, NULL);
memcpy(sendpacket, &tvsend, sizeof(tvsend));
len = datalen + sizeof(tvsend);
sendto(sockfd, sendpacket, len, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
}
void recv_packet()
{
int n, fromlen;
extern int errno;
signal(SIGALRM, statistics);
fromlen = sizeof(from_addr);
while (1) {
alarm(MAX_WAIT_TIME);
if ((n = recvfrom(sockfd, recvpacket, sizeof(recvpacket), 0, (struct sockaddr *)&from_addr, &fromlen)) < 0) {
if (errno == EINTR) {
cerr << "recvfrom() timeout" << endl;
return;
}
cerr << "recvfrom() error" << endl;
return;
}
gettimeofday(&tvrecv, NULL);
nreceived++;
if (n < datalen + sizeof(tvsend)) {
cerr << "received packet size is less than data length + sizeof(timeval)" << endl;
continue;
}
struct timeval *tvsend = (struct timeval *)recvpacket;
struct timeval *tvrecv = (struct timeval *)(recvpacket + sizeof(struct timeval));
struct timeval tvresult;
timersub(tvrecv, tvsend, &tvresult);
printf("%d bytes from %s: icmp_seq=%u ttl=%d time=%.3f ms\n", n, inet_ntoa(from_addr.sin_addr), nreceived, from_addr.sin_ttl, tvresult.tv_sec * 1000.0 + tvresult.tv_usec / 1000.0);
}
}
void statistics(int signo)
{
printf("\n--- %s ping statistics ---\n", inet_ntoa(dest_addr.sin_addr));
printf("%d packets transmitted, %d received, %%%d lost\n", nsend, nreceived, (nsend - nreceived) / nsend * 100);
exit(0);
}
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;
}
```
该程序使用 ICMP 协议实现 ping 命令的功能。具体实现方式为发送一个 ICMP 报文(包含时间戳),等待接收一个 ICMP 报文并计算收到报文的时间与发送报文的时间的差值。程序默认发送 3 个 ICMP 报文,最长等待时间为 5 秒。程序运行后输出每个接收到的 ICMP 报文的信息,包括 IP 地址、TTL、收到报文的时间与发送报文的时间的差值。
阅读全文