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

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

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

   下面是系统的原理图:

UDP与TCP数据包的延迟探测系统_第1张图片

 

   UDP与TCP数据包的延迟探测系统_第2张图片

    由于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

UDP与TCP数据包的延迟探测系统_第3张图片

  udpping

UDP与TCP数据包的延迟探测系统_第4张图片

UDP与TCP数据包的延迟探测系统_第5张图片

 

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

  1 // frping.c 1.4
  2 // date : 20150108
  3 // [email protected]
  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                         else
113                             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                         else
129                             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     else
164        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 name
174         hp = gethostbyname(server_name);
175     }
176     else
177     { // Convert nnn.nnn address to a usable one
178         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     else
190        printf("Client: gethostbyaddr() is OK.\n");
191     // Copy the resolved information into the sockaddr_in structure
192     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 parameters
202     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     else
218        printf("Client: socket() is OK.\n");
219  
220     // Notice that nothing in this code is specific to whether we
221     // 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 not
224     //    actually establish the connection as a stream (TCP) socket
225     //    would. Instead, TCP/IP establishes the remote half of the
226     //    (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     else
237        printf("Client: connect() is OK.\n");
238  
239     // Test sending some string
240     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=256
251          //wsprintf((LPSTR)Buffer,(LPSTR)"%d", loopcount);
252          Buffer[0]=seq;
253          loopcount++;
254          //// timestamp
255          timestamp_pre=timeGetTime();
256          //printf("-->%d\n",timeGetTime());
257          retval = 
258              send(conn_socket, Buffer, 1, 0);//send only one probe packet
259          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          //else
269          // 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          //// timestamp
277          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 no
319         // '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         else
337         {
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 // [email protected]
  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     //time
120     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           tm = time(NULL);
143           t = localtime(&tm);
144           strftime(newtime, 16, "%Y%m%d%H%M%S", t);
145           printf("current-time:%s  total-clients:%lu\n",newtime,counter);
146         }
147 
148     }
149 
150     close(server_socket);
151 
152     return 0;
153 }
View Code

  UDP Echo Server(On GNU/Linux Platform)

  1 // date : 20150108
  2 // [email protected]
  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           tm = time(NULL);
100           t = localtime(&tm);
101           strftime(newtime, 16, "%Y%m%d%H%M%S", t);
102           printf("current-time:%s  total-clients:%lu\n",newtime,counter);
103       }
104   }
105   close(sockfd);  
106 }
View Code

 

你可能感兴趣的:(tcp)