摘要
本文记录通过数据报套接字来检测UDP数据包的延迟和丢包的思路和简单的代码实现。
思路
UDP协议及用户数据报协议在传输层提供了无连接、不可靠的传输服务,端到端的延迟以及丢包率是反应当前网络环境好坏的重要评价标准。Ping检测延迟的方式是:发送端发送一个ICMP包给接收端,接收端接收到ICMP包之后向发送端回应一个包,发送端可以计算出往返时间(RTT),本文通过套接字使用类似于Ping的思路来计算RTT来反映延迟的大小,可以多次发包根据多次的结果来计算一个平均的RTT;丢包率可以通过指定发送端发包的数量,然后在接收端统计接收成功的数量,就可以计算出当前丢包率。
说明
- 数据报套接字(SOCK-DGRAM)在传输层使用的UDP协议,所以在创建socket的时候一定要指定使用SOCK_DGRAM类型的套接字,这样系统在封装数据包的时候才使用的是UDP协议。
- 因为不同设备的网络数据发送能力和接受能力都有限,发送端每次发送内容的长度也就是数据包的大小,以及发送速率都是影响接收端延迟和丢包率的因素;因此将发送数据大小(bytes)、发送数据包数量、发送间隔(ms)都作为程序的参数,根据不用的应用场景指定对应的参数,得到的结果会有一定的参考价值。
代码实现
加入头文件
代码实在windows环境下写的,所以发送端和接收端调用函数之前都需要加入头文件和预处理指令
#include <iostream>
#include <ctime>
#include <winsock2.h>
#pragma comment (lib, "ws2_32.lib") //加载 ws2_32.dll
发送端函数
//参数分别为接收端的IP地址、端口以及本次发包的数量和每个包的内容长度
void udp_delay_detect_client(const char* ip,int port,int packetSize,int packetNum)
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
//创建UDP套接字
SOCKET sock = socket(PF_INET, SOCK_DGRAM, 0);
//服务器地址信息
sockaddr_in servAddr;
memset(&servAddr, 0, sizeof(servAddr)); //每个字节都用0填充
servAddr.sin_family = PF_INET;
servAddr.sin_addr.s_addr = inet_addr(ip);
servAddr.sin_port = htons(port);
//不断获取用户输入并发送给服务器,然后接受服务器数据
SOCKADDR clntAddr;