UDP与TCP数据包的延迟探测系统,udptcp数据包探测
UDP与TCP数据包的延迟探测系统,udptcp数据包探测
最近需要测试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
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 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) UDP Echo Server(On GNU/Linux Platform)
评论暂时关闭