首页 > 代码库 > UDP与TCP数据包的延迟探测系统

UDP与TCP数据包的延迟探测系统

  最近需要测试Akamai的几个节点对数据包加速加速效果,下面是win32上面的一个udp、tcp ping的探测程序。

   程序参考了http://www.tenouk.com/Winsock/Winsock2example9.html中的代码。

   下面是系统的原理图:

技术分享

 

   技术分享

    由于udp的特殊性,采用在应用层添加seq的方案,保证回包的准确性(经过测试发现,nmap项目的nping探测器由于没有进行回包准确性的验证,导致最后的统计数据错误,朋友们应该注意)。

    而tcp本身就是一种数据流而已,它的机制导致了粘包与分包的问题,tcp探测程序则避开了这两个问题。

    最终效果图:

    win-cmd:

>.\nping.exe -e UDP -c 500 -p 9999 yfdc.org>.\nping.exe -e TCP -c 500 -p 9999 yfdc.org

    tcpping

技术分享

  udpping

技术分享

技术分享

 

   WIN客户端探测程序:(vs2008,若用其他编译器,小改一下即可)

技术分享
  1 // frping.c 1.4  2 // date : 20150108  3 // yunthanatos@163.com  4 // you are free to use the codes :)  5   6 #include "stdafx.h"  7 #include <Winsock2.h>  8 #include <stdio.h>  9 #include <WinBase.h> 10 #include <windows.h> 11 #include <Mmsystem.h> 12 #include <sys/timeb.h> 13 #include <time.h> 14  15 #pragma comment(lib,"ws2_32.lib") 16 #pragma comment( lib,"winmm.lib" ) 17  18 /// 19 #include "stdafx.h" 20  21 // Client program example 22 #define WIN32_LEAN_AND_MEAN 23 #include <winsock2.h> 24 #include <stdlib.h> 25 #include <stdio.h> 26 #include <string.h>  27 #pragma comment(lib,"ws2_32.lib") 28  29  30 void Usage(char *progname) 31 { 32     fprintf(stderr,"Usage: %s -e [protocol] -n [server name/IP] -p [port_num] -l [iterations] -d [delay_ms] -t [timeout_s] -c [iterations] ip\n", progname); 33     fprintf(stderr,"Where:\n\tprotocol is one of TCP or UDP\n"); 34     fprintf(stderr,"\t- server is the IP address or name of server\n"); 35     fprintf(stderr,"\t- port_num is the port to listen on\n"); 36     fprintf(stderr,"\t- iterations is the number of loops to execute.\n"); 37     fprintf(stderr,"\t- (-l by itself makes client run in an infinite loop,\n"); 38     fprintf(stderr,"\t- Hit Ctrl-C to terminate it)\n"); 39     fprintf(stderr,"\t- The defaults are TCP , localhost and 2007\n"); 40     WSACleanup(); 41     exit(1); 42 } 43  /* 44 int _tmain(int argc, _TCHAR* argv[]) 45 { 46     return 0; 47 }*/ 48  49  50 int _tmain(int argc, char **argv) 51 { 52     char Buffer[128]; 53      54     // default to localhost 55     char *server_name= "localhost"; 56     unsigned short port = 1080; 57     int retval, loopflag = 0; 58     int i, loopcount, maxloop=50; 59     unsigned int addr; 60     int socket_type = SOCK_STREAM;//SOCK_DGRAM; 61     struct sockaddr_in server; 62     struct hostent *hp; 63     WSADATA wsaData; 64     SOCKET  conn_socket; 65   66     // 67     char rcvBuffer[128]; 68     int timestamp_post; 69     int timestamp_pre; 70     int delay_ms=500; 71     int timeout_s=1000; 72     int err; 73     int loss_counter=0; 74     int probe_counter=0; 75     int minrttms=10000000; 76     int maxrttms=0; 77     int sumrttms=0; 78     int deltarttms; 79     char * nonopt=NULL; 80     float float_a,float_b; 81 //socket_type==SOCK_DGRAM)?("UDP"):("TCP"),server_name,port,maxloop,delay_ms,timeout_s 82  83     if (argc >1) 84        { 85         for(i=1; i<argc; i++) 86         { 87             if ((argv[i][0] == -) || (argv[i][0] == /)) 88            { 89                 switch(tolower(argv[i][1])) 90                  { 91                     case e: 92                         if (!stricmp(argv[i+1], "TCP")) 93                             socket_type = SOCK_STREAM; 94                         else if (!stricmp(argv[i+1], "UDP")) 95                             socket_type = SOCK_DGRAM; 96                         else 97                             Usage(argv[0]); 98                         i++; 99                         break;100                     case n:101                         server_name = argv[++i];102                         break;103                     case p:104                         port = atoi(argv[++i]);105                         break;106                     case l:107                         loopflag =1;108                         if (argv[i+1]) {109                             if (argv[i+1][0] != -)110                                 maxloop = atoi(argv[i+1]);111                         }112                         else113                             maxloop = -1;114                         i++;115                         break;116                     case d:117                         delay_ms = atoi(argv[++i]);118                         break;119                     case t:120                         timeout_s = atoi(argv[++i]);121                         break;122                     case c:123                         loopflag =1;124                         if (argv[i+1]) {125                             if (argv[i+1][0] != -)126                                 maxloop = atoi(argv[i+1]);127                         }128                         else129                             maxloop = -1;130                         i++;131                         break;132                     case -: // ignore options --133                         if(argv[i][2]==d)134                             i++;135                         break;136                     default:137                         Usage(argv[0]);138                         break;139                 }140             }141             else {142                 //Usage(argv[0]);143                 nonopt=argv[i];144                 //printf("nonopt:%s\n",nonopt);145             }146         }147     }148     if(nonopt!=NULL) {149         server_name=nonopt;150     }151 152     //fprintf(stderr,"Usage: %s -e [protocol] -n [server name/IP] -p [port_num] -l [iterations] -d [delay_ms] -t [timeout_s] -c [iterations] ip\n", progname);153     printf("\n proto_type:%s \n peer_ip_addr:%s\n peer_proto_port:%d\n probe_counts:%d \n probe_interval_ms:%d \n probe_timeout_ms:%d\n\n",154         (socket_type==SOCK_DGRAM)?("UDP"):("TCP"),server_name,port,maxloop,delay_ms,timeout_s);    155     //////    156  157     if ((retval = WSAStartup(0x202, &wsaData)) != 0)158     {159        fprintf(stderr,"Client: WSAStartup() Error %d\n", retval);160         WSACleanup();161         return -1;162     }163     else164        printf("Client: WSAStartup() is OK.\n");165  166     if (port == 0)167     {168         Usage(argv[0]);169     }170     // Attempt to detect if we should call gethostbyname() or gethostbyaddr()171     /*172     if (isalpha(server_name[0]))173     {   // server address is a name174         hp = gethostbyname(server_name);175     }176     else177     { // Convert nnn.nnn address to a usable one178         addr = inet_addr(server_name);179         hp = gethostbyaddr((char *)&addr, 4, AF_INET);180     }181     */182     hp = gethostbyname(server_name);183     if (hp == NULL )184     {185         fprintf(stderr,"Client: Cannot resolve address \"%s\": Error %d\n", server_name, WSAGetLastError());186         WSACleanup();187         exit(1);188     }189     else190        printf("Client: gethostbyaddr() is OK.\n");191     // Copy the resolved information into the sockaddr_in structure192     memset(&server, 0, sizeof(server));193     memcpy(&(server.sin_addr), hp->h_addr, hp->h_length);194     server.sin_family = hp->h_addrtype;195     server.sin_port = htons(port);196 197     198     ///************* make a socket ******************/// 199     conn_socket = socket(AF_INET, socket_type, 0); /* Open a socket */200 201     // set time out parameters202     err=setsockopt(conn_socket,SOL_SOCKET,SO_RCVTIMEO,(const char *)&timeout_s,sizeof(timeout_s));203     if(err!=0)204       {205           printf("error:setsockopt \n");206           closesocket(conn_socket);207           WSACleanup();208           return 1;209       }    210     211     if (conn_socket <0 )212     {213         fprintf(stderr,"Client: Error Opening socket: Error %d\n", WSAGetLastError());214         WSACleanup();215         return -1;216     }217     else218        printf("Client: socket() is OK.\n");219  220     // Notice that nothing in this code is specific to whether we221     // are using UDP or TCP.222     // We achieve this by using a simple trick.223     //    When connect() is called on a datagram socket, it does not224     //    actually establish the connection as a stream (TCP) socket225     //    would. Instead, TCP/IP establishes the remote half of the226     //    (LocalIPAddress, LocalPort, RemoteIP, RemotePort) mapping.227     //    This enables us to use send() and recv() on datagram sockets,228     //    instead of recvfrom() and sendto()229     printf("Client: Client connecting to: %s.\n", hp->h_name);230     if (connect(conn_socket, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR)231     {232         fprintf(stderr,"Client: connect() Error : %d\n", WSAGetLastError());233         WSACleanup();234         return -1;235     }236     else237        printf("Client: connect() is OK.\n");238  239     // Test sending some string240     loopcount = 0;241     242     ///**********FSM: START************/// 243     probe_counter=0;244     unsigned char seq=1;245     unsigned char * ptr;246     247     while(1)248     {249          ///**********FSM: Send New Sequence UDP Packet************/// 250          // single byte : 2^8=256251          //wsprintf((LPSTR)Buffer,(LPSTR)"%d", loopcount);252          Buffer[0]=seq;253          loopcount++;254          //// timestamp255          timestamp_pre=timeGetTime();256          //printf("-->%d\n",timeGetTime());257          retval = 258              send(conn_socket, Buffer, 1, 0);//send only one probe packet259          probe_counter++;260          if (retval == SOCKET_ERROR)261          {262             fprintf(stderr,"Client: send(): Error %d.\n", WSAGetLastError());263             closesocket(conn_socket);264             WSACleanup();265             goto STATISTICS;266             return -1;267          }268          //else269          // printf("Client: send() is OK.\n");270 271          272  RECV:273           ///**********FSM: recv************/// 274           memset(rcvBuffer,0,128);275          retval = recv(conn_socket, rcvBuffer,1, 0);276          //// timestamp277          timestamp_post=timeGetTime();278          279          if(retval == SOCKET_ERROR)280          {281              ///**********FSM: connection timeout************///282             fprintf(stderr,"Client: recv() : Connection timed out ------------------------> %d \n", WSAGetLastError());283             loss_counter++;284             goto LOOP_END_BEGIN;285             //closesocket(conn_socket);286             //WSACleanup();287             //return -1;288          }289          else 290          {    291             ///**********FSM: Wrong Seq Packet************///292             rcvBuffer[retval]=0;293             /*294             if( atoi(rcvBuffer)!=(loopcount-1) ) {295                 printf("<%s>\n",rcvBuffer);296                 goto RECV;297             }*/298             ptr=(unsigned char *)rcvBuffer;299             if( (*ptr)!=seq ) {300                 printf("<%d>\n",rcvBuffer[0]);301                 goto RECV;302             }    303             304          }305 306         ///**********FSM: Check OK :) ************///307         printf("Client: Sent data \"%d\"\n", Buffer[0]);308         printf("Client: recv() is OK.\n");309         if(retval>0) {310              printf("----------------------------> %d\n",timestamp_post-timestamp_pre);311           deltarttms=timestamp_post-timestamp_pre;312           sumrttms=sumrttms+deltarttms;313           if(maxrttms<deltarttms) maxrttms=deltarttms;314           if(minrttms>deltarttms) minrttms=deltarttms;315           //if(deltarttms==0) deltarttms=1;316           317         }318         // We are not likely to see this with UDP, since there is no319         // ‘connection‘ established.320         if (retval == 0)321         {322             printf("Client: Server closed connection.\n");323             closesocket(conn_socket);324             WSACleanup();325             goto STATISTICS;326             return -1;327         }328         printf("Client: Received %d bytes, data \"%d\" from server.\n", retval, Buffer[0]);329 330         LOOP_END_BEGIN:331         if (!loopflag)332         {333             printf("Client: Terminating connection...\n");334             break;335         }336         else337         {338             if ((loopcount >= maxloop) && (maxloop >0))339             break;340         }341         Sleep(delay_ms);342         seq++;343         if(seq==0) seq=1;344     }345 346     STATISTICS:347 //    printf("\nsumrttms:%d,maxrttms:%d,minrttms:%d,loss_counter:%d,probe_counter:%d\n",sumrttms,maxrttms,minrttms,loss_counter,probe_counter);348 //    printf("mean:%d,better-mean:%d\n",(sumrttms)/(probe_counter-loss_counter),(probe_counter>(loss_counter+2))?((sumrttms-maxrttms-minrttms)/(probe_counter-loss_counter-2)):((sumrttms)/(probe_counter-loss_counter)));        349     float_a=loss_counter;350     float_b=probe_counter;351 //    printf("packet loss rate: %.2f%%\n\n\n",float_a*100/float_b);352 353     closesocket(conn_socket);354     WSACleanup();355     356     if((probe_counter!=0)&&(probe_counter!=loss_counter))357     {358         printf("mean:%d.000,better-mean:%d.000\n\n",(sumrttms)/(probe_counter-loss_counter),(probe_counter>(loss_counter+2))?((sumrttms-maxrttms-minrttms)/(probe_counter-loss_counter-2)):((sumrttms)/(probe_counter-loss_counter)));   359         printf("\nMax rtt: %d.000ms | Min rtt: %d.000ms | Avg rtt: %d.000ms\n",maxrttms,minrttms,(probe_counter>(loss_counter+2))?((sumrttms-maxrttms-minrttms)/(probe_counter-loss_counter-2)):((sumrttms)/(probe_counter-loss_counter)));360         printf("Raw packets sent: %d | Rcvd: %d | Lost: %d (%.2f%%)\n",probe_counter,probe_counter-loss_counter,loss_counter,float_a*100/float_b);361     }362     else if(probe_counter>0)363     {364         printf("\nMax rtt: N/Ams | Min rtt: N/Ams | Avg rtt: N/Ams\n");365         printf("Raw packets sent: %d | Rcvd: 0 | Lost: %d (100%%)\n",probe_counter,probe_counter);366         printf("Error \n");367     }368     else {369         printf("\nMax rtt: N/Ams | Min rtt: N/Ams | Avg rtt: N/Ams\n");370         printf("Raw packets sent: N/A | Rcvd: N/A | Lost: %d (N/A%%)\n");371         printf("Error \n");372     }373  374 return 0;375 }
View Code

   TCP Multithread Echo Server(On GNU/Linux Platform)

技术分享
  1 //multi_thread_server.c  2 // gcc -o multi_thread_server multi_thread_server.c -lpthread  3   4 // date : 20150108  5 // yunthanatos@163.com  6 // you are free to use the codes :)  7   8   9 #include <netinet/in.h>    // for sockaddr_in 10 #include <sys/types.h>    // for socket 11 #include <sys/socket.h>    // for socket 12 #include <stdio.h>        // for printf 13 #include <stdlib.h>        // for exit 14 #include <string.h>        // for bzero 15 #include <pthread.h> 16 #include <sys/errno.h>    // for errno 17  18 #define LENGTH_OF_LISTEN_QUEUE  512 19 #define BUFFER_SIZE 128 20  21 void * talk_to_client(void *data) 22 { 23     int new_server_socket = (int)data; 24     char buffer[BUFFER_SIZE]; 25     int length ; 26     int max_times=600; 27  28     //echo back 29     while(max_times--) { 30         bzero(buffer,BUFFER_SIZE); 31         length = recv(new_server_socket,buffer,BUFFER_SIZE-2,0); 32         if(length==-1||length==0) 33             break; 34         buffer[length]=0; 35         send(new_server_socket,buffer,strlen(buffer),0); 36     } 37     //printf("disconnect...\n"); 38     close(new_server_socket);  39     pthread_exit(NULL); 40 } 41  42 void Usage(char *progname) { 43     fprintf(stderr,"Usage: %s -p [port_num]\n", progname);         44     fprintf(stderr,"Usage: nohup %s -p [port_num] &>%s.log &\n",progname,progname);         45 } 46  47 int main(int argc, char **argv) 48 { 49     //ÉèÖÃÒ»¸ösocketµØÖ·½á¹¹server_addr,´ú±í·þÎñÆ÷internetµØÖ·, ¶Ë¿Ú 50     struct sockaddr_in server_addr; 51     bzero(&server_addr,sizeof(server_addr)); //°ÑÒ»¶ÎÄÚ´æÇøµÄÄÚÈÝÈ«²¿ÉèÖÃΪ0 52     server_addr.sin_family = AF_INET; 53     server_addr.sin_addr.s_addr = htons(INADDR_ANY); 54  55     int port; 56     int i; 57  58     if (argc >1) { 59         for(i=1; i<argc; i++) { 60             if ((argv[i][0] == -) || (argv[i][0] == /)) { 61                 switch(tolower(argv[i][1])) { 62                      case p: 63                         port=atoi(argv[++i]);server_addr.sin_port = htons(port); 64                         break; 65                     default: 66                         Usage(argv[0]); 67                         return 1; 68                         break; 69                 } 70             } 71         } 72     } 73     else { 74         Usage(argv[0]); 75         return 1; 76     } 77  78     //´´½¨ÓÃÓÚinternetµÄÁ÷ЭÒé(TCP)socket,ÓÃserver_socket´ú±í·þÎñÆ÷socket 79     int server_socket = socket(AF_INET,SOCK_STREAM,0); 80     if( server_socket < 0) 81     { 82         fprintf(stderr,"Create Socket Failed!"); 83         exit(1); 84     } 85      86     // set time out parameters 87     /* 88     int timeout_s=1000;//ms 89     int err=setsockopt(server_socket,SOL_SOCKET,SO_RCVTIMEO,(const char *)&timeout_s,sizeof(timeout_s)); 90     if(err!=0) 91       { 92           printf("error:setsockopt \n"); 93           close(server_socket); 94           return 1; 95       }     96     */ 97      98     //°ÑsocketºÍsocketµØÖ·½á¹¹ÁªÏµÆðÀ´ 99     if( bind(server_socket,(struct sockaddr*)&server_addr,sizeof(server_addr)))100     {101         fprintf(stderr,"Server Bind Port : %d Failed!",port); 102         close(server_socket);103         exit(1);104     }105     106     //server_socketÓÃÓÚ¼àÌý107     if ( listen(server_socket, LENGTH_OF_LISTEN_QUEUE) )108     {109         fprintf(stderr,"Server Listen Failed!"); 110         close(server_socket);111         exit(1);112     }113     114     struct sockaddr_in client_addr;115     socklen_t length = sizeof(client_addr);116     int new_server_socket;117     unsigned long counter=0;118 119     //time120     char newtime[16] ;121     time_t tm = time(NULL);122     struct tm *t = localtime(&tm);123     124     while(1) 125     {126         new_server_socket = accept(server_socket,(struct sockaddr*)&client_addr,&length);127         if ( new_server_socket < 0)128         {129             printf("Server Accept Failed!/n");130             break;131         }132         pthread_t child_thread;133         pthread_attr_t child_thread_attr;134         pthread_attr_init(&child_thread_attr);135         pthread_attr_setdetachstate(&child_thread_attr,PTHREAD_CREATE_DETACHED);136         if( pthread_create(&child_thread,&child_thread_attr,talk_to_client, (void *)new_server_socket) < 0 )137             printf("pthread_create Failed : %s/n",strerror(errno));138 139         counter++;140 141         if((counter%50)==0) {142           strftime(newtime, 16, "%Y%m%d%H%M%S", t);143           printf("current-time:%s  total-clients:%lu\n",newtime,counter);144         }145 146     }147 148     close(server_socket);149 150     return 0;151 }
View Code

    UDP Echo Server(On GNU/Linux Platform)

技术分享
  1 // date : 20150108  2 // yunthanatos@163.com  3 // you are free to use the codes :)  4   5 #include<stdio.h>  6 #include<string.h>  7 #include<unistd.h>  8 #include<sys/types.h>  9 #include<sys/socket.h> 10 #include<stdlib.h> 11 #include<netinet/in.h> 12 #include<arpa/inet.h> 13 #include <time.h> 14 #include <stdio.h> 15  16 #define MAXBUFSIZE 50 17  18 void Usage(char *progname) { 19     fprintf(stderr,"Usage: %s -p [port_num]\n", progname);         20     fprintf(stderr,"Usage: nohup %s -p [port_num] &>%s.log &\n",progname,progname);         21 } 22  23 int main(int argc, char **argv) 24 { 25   int sockfd; 26   struct sockaddr_in server; 27   struct sockaddr_in client; 28   socklen_t addrlen; 29   int num; 30   char buf[MAXBUFSIZE]; 31   unsigned long counter=0; 32    33   //time 34   char newtime[16] ; 35   time_t tm = time(NULL); 36   struct tm *t = localtime(&tm); 37  38   int port; 39   int i; 40    41   if (argc >1) { 42       for(i=1; i<argc; i++) { 43           if ((argv[i][0] == -) || (argv[i][0] == /)) { 44               switch(tolower(argv[i][1])) { 45                   case p: 46                       port=atoi(argv[++i]); 47                       break; 48                   default: 49                       Usage(argv[0]); 50                       return 1; 51                       break; 52               } 53           } 54       } 55   } 56   else { 57       Usage(argv[0]); 58       return 1; 59   } 60  61   if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)  62   { 63       perror("Creatingsocket failed."); 64       exit(1); 65   } 66  67   bzero(&server,sizeof(server)); 68   server.sin_family=AF_INET; 69   server.sin_port=htons(port); 70   server.sin_addr.s_addr= htonl (INADDR_ANY); 71  72   if(bind(sockfd, (struct sockaddr *)&server, sizeof(server)) == -1) 73   { 74       perror("Bind()error."); 75       exit(1); 76   }    77  78   addrlen=sizeof(client); 79  80   counter=0;     81   while(1)     82   { 83            84         bzero(buf,MAXBUFSIZE); 85       num =recvfrom(sockfd,buf,MAXBUFSIZE-2,0,(struct sockaddr*)&client,&addrlen);                                     86  87       if (num < 0) 88       { 89           perror("recvfrom() error\n"); 90           exit(1); 91       } 92       counter++; 93       buf[num] = \0; 94  95       sendto(sockfd,buf,strlen(buf),0,(struct sockaddr *)&client,addrlen); 96  97       //log 98       if((counter%100)==0) { 99           strftime(newtime, 16, "%Y%m%d%H%M%S", t);100           printf("current-time:%s  total-clients:%lu\n",newtime,counter);101       }102   }103   close(sockfd);  104 }
View Code

 

UDP与TCP数据包的延迟探测系统