1.UDP通信流程
2.client (发送端)
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
#include <sys/time.h>
using namespace std;
//获取时间的函数
long GetTime(){
struct timeval tv;
gettimeofday(&tv,NULL);
return tv.tv_sec*1000000 + tv.tv_usec;//单位为微妙
}
int main()
{
int sock_fd;
// 建立udp socket
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
if(sock_fd < 0)
{
perror("socket");
exit(1);
}
// 设置目的地址的IP和端口号
struct sockaddr_in addr_serv;
memset(&addr_serv, 0, sizeof(addr_serv));
addr_serv.sin_family = AF_INET;
addr_serv.sin_addr.s_addr = inet_addr("192.168.100.22");
addr_serv.sin_port = htons(12345);
int len;
len = sizeof(addr_serv);
struct Send
{
long time;
char buf[1024];
int count;
};
char buffer[50] = "Hello World!";
Send sd;
strncpy(sd.buf,buffer,strlen(buffer)+1);
sd.count = 0;
for(int i = 0;i < 100;i++){
sd.count++;
sleep(1);
sd.time = GetTime();
sendto(sock_fd, &sd, sizeof(sd), 0, (struct sockaddr *)&addr_serv, len);
cout << "client send: " <<"SendTime = " << sd.time <<", buf = " << sd.buf <<", count = " << sd.count << endl;
}
close(sock_fd);
return 0;
}
3.server(接收端)
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include<arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <sys/time.h>
using namespace std;
long GetTime(){
struct timeval tv;
gettimeofday(&tv,NULL);
return tv.tv_sec*1000000 + tv.tv_usec;//单位微秒
}
int main()
{
//创建socket
int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
if(sock_fd < 0)
{
perror("socket");
exit(1);
}
//设置本地IP和端口
struct sockaddr_in addr_serv;
int len;
memset(&addr_serv, 0, sizeof(struct sockaddr_in));
addr_serv.sin_family = AF_INET;
addr_serv.sin_port = htons(12345);
addr_serv.sin_addr.s_addr = htonl(INADDR_ANY);//htonl(INADDR_ANY)针对多张网卡,任意网卡的地址都行
len = sizeof(addr_serv);
// 绑定socket,接收端必须要bind绑定
if(bind(sock_fd, (struct sockaddr *)&addr_serv, sizeof(addr_serv)) < 0)
{
perror("bind error:");
exit(1);
}
struct Data
{
long time;
char buf[1024];
int count;
};
struct sockaddr_in addr_client;
char buffer[2048] ={0};
//num用于网络模拟丢包时,统计实际接受到的数据数量
int num = 0;
while(1)
{
cout <<"--------------------------------------------------------------------------------"<< endl;
recvfrom(sock_fd, buffer, 2048, 0, (struct sockaddr *)&addr_client, (socklen_t *)&len);
long ReceiveTime = GetTime();
std::cout << "UDP data from " << inet_ntoa(addr_client.sin_addr) << std::endl;
struct Data data;
memcpy(&data,buffer,sizeof(data)+1);
long timeDelay = ReceiveTime- data.time;//计算传输时延
num++;
cout <<"SendTime: "<< data.time <<", ReceiveTime: "<< ReceiveTime << ", timeDelay: "<< timeDelay << endl;
cout <<"count = "<< data.count << ", Message: "<< data.buf << ", num = " << num << endl;
}
close(sock_fd);
return 0;
}
4.测试
client发送端:
server接收端:
5.网络环境模拟
模拟网络延时
//将 enp4s0 网卡的传输设置为延迟100毫秒发送
tc qdisc add dev enp4s0 root netem delay 100ms
//将 enp4s0 网卡的传输设置为延迟 100ms ± 10ms (90 ~ 110 ms 之间的任意值)发送,模拟时延抖动
tc qdisc add dev enp4s0 root netem delay 100ms 10ms
//将 enp4s0 网卡的传输设置为 100ms ,同时,大约有 30% 的包会延迟 ± 10ms 发送
tc qdisc add dev enp4s0 root netem delay 100ms 10ms 30%
测试结果如下,延时明显增加100ms:
模拟网络丢包
//将 enp4s0 网卡的传输设置为随机丢掉 50% 的数据包
tc qdisc add dev enp4s0 root netem loss 50%
//将 enp4s0 网卡的传输设置为随机丢掉 50% 的数据包,成功率为 30%
tc qdisc add dev enp4s0 root netem loss 50% 30%
删除模拟配置
//删除enp4s0 模拟配置
tc qdisc del dev enp4s0 root