最近需要测试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 // [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 }
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 }
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 }