UDP网络延迟测试程序

以太网(Ethernet)数据帧的长度必须在46-1500字节之间,这是由以太网的物理特性决定的
 
这个1500字节被称为链路层的MTU(最大传输单元). 
 
但这并不是指链路层的长度被限制在1500字节,其实这这个MTU指的是链路层的数据区
 
并不包括链路层的首部和尾部的18个字节.

因为IP数据报的首部为20字节,所以IP数据报的数据区长度最大为1480字节

又因为UDP数据报的首部8字节,所以UDP数据报的数据区最大长度为1472字节

鉴于Internet上的标准MTU值为576字节,所以我建议在进行InternetUDP编程时

网络延迟测试程序

服务器端:

#include <stdio.h>

#include <winsock2.h>

#pragma comment(lib,"ws2_32.lib")

int _tmain(int argc, _TCHAR* argv[])

{

     WSADATA wsa;

     WSAStartup(MAKEWORD(2,2),&wsa);

     struct sockaddr_in addr;

     addr.sin_family = AF_INET;

     addr.sin_addr.s_addr =  inet_addr("192.168.1.101");

     addr.sin_port = htons(7000);

     int len  = sizeof(addr);

     struct sockaddr_in addr_server;

     addr_server.sin_family = AF_INET;

     addr_server.sin_port = htons(8000);

     addr_server.sin_addr.s_addr =  inet_addr("192.168.1.101");

     SOCKET serversocket = socket(AF_INET,SOCK_DGRAM,0);

     bind(serversocket,(struct sockaddr*)&addr_server,sizeof(addr_server));

    

     struct sockaddr_in addr_from;

     int  fromlen = sizeof(addr_from);

    

     while(1){

         char frombuff[1024] = "\0";

         printf("等待客户端输入信息!");

         if(recvfrom(serversocket,frombuff,sizeof(frombuff),0,(struct sockaddr*)&addr_from,&fromlen) == SOCKET_ERROR){

              printf("服务端接受有错误!!");

         }

         printf("客户端输入的是:%s\n",frombuff);

        //Sleep(5000);

         if(sendto(serversocket,frombuff,sizeof(frombuff),0,(struct sockaddr*)&addr,fromlen) == SOCKET_ERROR){

              printf("服务端发送错误!!");

         }

     }

     closesocket(serversocket);

     WSACleanup();

     return 0;

}

客户端:

#include <stdio.h>

#include <winsock2.h>

#include <time.h>

#pragma comment(lib,"ws2_32.lib")

int main(void)

{

     WSADATA wsa;

     WSAStartup(MAKEWORD(2,2),&wsa);

     SOCKET mySocket;

     mySocket = socket(AF_INET,SOCK_DGRAM,0);

     struct sockaddr_in addr;

     addr.sin_family = AF_INET;

     addr.sin_addr.s_addr =  inet_addr("192.168.1.101");

     addr.sin_port = htons(8000);

     int len  = sizeof(addr);

    

     struct sockaddr_in addr_client;

     addr_client.sin_family = AF_INET;

     addr_client.sin_port = htons(7000);

     addr_client.sin_addr.s_addr =  inet_addr("192.168.1.101");

     SOCKET clientsocket = socket(AF_INET,SOCK_DGRAM,0);

     bind(clientsocket,(struct sockaddr*)&addr_client,sizeof(addr_client));

     while(1){

         printf("请输入一段字符串用户测试延迟:");

         char buff[1024] = "\0";

         scanf("%s",buff);

        

        LARGE_INTEGER t1,t2,feq;

         QueryPerformanceFrequency(&feq);//每秒跳动次数

         if(sendto(clientsocket,buff,sizeof(buff),0,(struct sockaddr *)&addr,len) == SOCKET_ERROR) {

              printf("发送错误!!!");

         }

         QueryPerformanceCounter(&t1);//测前跳动次数

         if(recvfrom(clientsocket,buff,sizeof(buff),0,(struct sockaddr*)&addr,&len) == SOCKET_ERROR) {

              printf("接受错误!!!");

         }

         QueryPerformanceCounter(&t2);//测后跳动次数

        

         printf("从服务端返回:%s\n",buff);

         printf("--->>时间延迟:%f秒\n",((double)t2.QuadPart-(double)t1.QuadPart)/((double)feq.QuadPart));

     }

   

     closesocket(mySocket);

     WSACleanup();

     return 0;

}

主要就是用了QueryPerformanceFrequency(&feq)高精度性能计时器的频率函数和QueryPerformanceCounter(&t1)函数,

QueryPerformanceFrequency() - 基本介绍
类型:Win32API

原型:BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);

作用:返回硬件支持的高精度计数器的频率。

返回值:非零,硬件支持高精度计数器;零,硬件不支持,读取失败。
QueryPerformanceFrequency() - 技术特点供WIN9X使用的高精度定时器:QueryPerformanceFrequency()和QueryPerformanceCounter(),要求计算机从硬件上支持高精度定时器。

函数的原形是:
  BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);
  BOOL QueryPerformanceCounter (LARGE_INTEGER *lpCount);

数据类型LARGEINTEGER既可以是一个作为8字节长的整数,也可以是作为两个4字节长的整数的联合结构,其具体用法根据编译器是否支持64位而定。该类型的定义如下:
  typeef union _ LARGE_INTEGER
  {
   struct
   {
   DWORD LowPart;
   LONG HighPart;
   };
   LONGLONG QuadPart;
  } LARGE_INTEGER;

在定时前应该先调用QueryPerformanceFrequency()函数获得机器内部计时器的时钟频率。接着在需要严格计时的事件发生前和发生之后分别调用QueryPerformanceCounter(),利用两次获得的计数之差和时钟频率,就可以计算出事件经历的精确时间。测试函数SLEEP(100)的精确持续时间方法:
  LARGE_INTEGER litmp;
  LONGLONG qt1,qt2;
  double dft,dff,dfm;
  QueryPerformanceFrequency(&litmp);//获得时钟频率
  dff=(double)litmp.QuadPart;
  QueryPerformanceCounter(&litmp);//获得初始值
  qt1=litmp.QuadPart;Sleep(100);
  QueryPerformanceCounter(&litmp);//获得终止值
  qt2=litmp.QuadPart;
  dfm=(double)(qt2-qt1);
  dft=dfm/dff;//获得对应的时间值

需要注意的是DFT计算的结果单位是秒。

你可能感兴趣的:(UDP网络延迟测试程序)