Я написал программу для проверки связи с другим сервером, она работала хорошо (проверка прошла успешно, одноранговый сервер мог получить проверку связи и выполнить проверку связи), но я путаюсь с тем, почему время отклика становится все короче, время откликабыли около 100 мс раньше, через несколько секунд время отклика стало 2 мс или 1 мс.
Журнал печатался следующим образом:
from 10.9.9.9 msg_seq=1 ttl=64 rtt = 100 ms
from 10.9.9.9 msg_seq=2 ttl=64 rtt = 102 ms
from 10.9.9.9 msg_seq=3 ttl=64 rtt = 101 ms
from 10.9.9.9 msg_seq=4 ttl=64 rtt = 100 ms
........//after a few sencondes
from 10.9.9.9 msg_seq=280 ttl=64 rtt = 1 ms
from 10.9.9.9 msg_seq=281 ttl=64 rtt = 2 ms
from 10.9.9.9 msg_seq=282 ttl=64 rtt = 0 ms
Пожалуйста, введите следующий код:
#define PING_PKT_S 64
#define PORT_NO 0
#define PING_SLEEP_RATE 1000000
#define RECV_TIMEOUT 1
int pingloop=1;
struct ping_pkt {
struct icmphdr hdr;
char msg[PING_PKT_S-sizeof(struct icmphdr)];
};
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;
}
void intHandler(int dummy) {
pingloop=0;
}
long current_timestamp() {
struct timeval te;
gettimeofday(&te, NULL);
long milliseconds = te.tv_sec*1000LL + te.tv_usec/1000;
return milliseconds;
}
void display(void *buf, int bytes){
int i;
for ( i = (sizeof(struct iphdr)+sizeof(struct icmphdr)); i < bytes; i++ ){
printf("%c", ((unsigned char*)buf)[i]);
}
}
// make a ping request
void send_ping(int ping_sockfd, char *ping_ip) {
int ttl_val=64, msg_count=0, i, addr_len, msg_received_count=0;
struct ping_pkt pckt;
struct sockaddr_in r_addr;
struct timespec time_start, time_end;
// set socket options at ip to TTL and value to 64,
if (setsockopt(ping_sockfd, SOL_IP, IP_TTL, &ttl_val, sizeof(ttl_val)) != 0) {
printf("Setting socket options to TTL failed!\n");
return;
}else{
printf("\nSocket set to TTL..\n");
}
// send icmp packet in an infinite loop
while(pingloop) {
if(isActiveNow()){
printf("--current is active!\n");
sleep(5);
continue;
}
//filling packet
bzero(&pckt, sizeof(pckt));
pckt.hdr.type = ICMP_ECHO;
pckt.hdr.un.echo.id = getpid();
for ( i = 0; i < 10; i++ ){
pckt.msg[i] = 'w';
}
pckt.msg[i] = 0;
pckt.hdr.un.echo.sequence = msg_count++;
pckt.hdr.checksum = checksum(&pckt, sizeof(pckt));
long s1 = current_timestamp();
struct hostent *hostentObj;
hostentObj = gethostbyname(ping_ip);
struct sockaddr_in ping_addr;
ping_addr.sin_port = 0;
ping_addr.sin_family = hostentObj->h_addrtype;
ping_addr.sin_addr.s_addr = *(long*) hostentObj->h_addr;
//Using synchronize
if ( sendto(ping_sockfd, &pckt, sizeof(pckt), 0, (struct sockaddr*) &ping_addr, sizeof(ping_addr)) <= 0) {
printf("\nPacket Sending Failed!\n");
}
struct timeval tv_out;
tv_out.tv_sec = 10;
tv_out.tv_usec = 0;
struct sockaddr_in peerAddr;
unsigned char buf[1024];
int len=sizeof(peerAddr);
bzero(buf, sizeof(buf));
int bytes_received = recvfrom(ping_sockfd, buf, sizeof(buf), 0, (struct sockaddr*)&peerAddr, &len);
if (bytes_received > 0) {
printf("ICMP packet received from %s\n", inet_ntoa(peerAddr.sin_addr));
struct icmphdr *icmp = (struct icmphdr *) (buf + sizeof(struct iphdr));
switch (icmp->type) {
case ICMP_ECHOREPLY:{
printf("Type: ICMP_ECHO--REPLY----------\n");
long s2 = current_timestamp();
printf("from %s msg_seq=%d ttl=%d rtt = %ld ms \n", ping_ip, msg_count,ttl_val, (s2-s1));
display(buf, bytes_received);
break;
};
case ICMP_DEST_UNREACH:{
printf("Type: ICMP_DEST_UNREACH---WRONG\n");
failedNum++;
break;
}
case ICMP_SOURCE_QUENCH: printf("Type: ICMP_SOURCE_QUENCH\n"); break;
case ICMP_REDIRECT: printf("Type: ICMP_REDIRECT\n"); break;
case ICMP_ECHO:{
printf("Type: ICMP_ECHO-----\n");
long s2 = current_timestamp();
printf("from %s msg_seq=%d ttl=%d rtt = %ld ms \n", ping_ip, msg_count,ttl_val, (s2-s1));
display(buf, bytes_received);
break;
}
default: printf("Type: <0x%02x>\n", icmp->type); break;
}
}
}
}
// Driver Code
int main(int argc, char *argv[]){
int sockfd;
char myIp[64]="10.1.1.10";
char *peerIp = "10.9.9.9";
sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
struct sockaddr_in r_addr;
r_addr.sin_family = AF_INET;
r_addr.sin_addr.s_addr = inet_addr(myIp);
r_addr.sin_port = 0;
bind(sockfd, (struct sockaddr *) &r_addr, sizeof(r_addr));
signal(SIGINT, intHandler);//catching interrupt
//send pings continuously
send_ping(sockfd, peerIp);
return 0;
}