Socket基础五:基于数据报套接字的网络程序(udp丢包测试)
作者:刘磊 2020.4.27 参考书目:《Windows网络编程》刘琰等著
一、功能函数
1、int udp_server_fun_packetloss(SOCKET s){
int iResult = 0;
int count = 0;
struct sockaddr_in cliaddr;
int addrlen = sizeof(sockaddr_in);
char recvline[MAXLINE];
do {
memset(recvline, 0, MAXLINE); //接收数据
iResult = recvfrom(s, recvline, MAXLINE, 0, (SOCKADDR *)&cliaddr, &addrlen);
if (iResult > 0)
count++;
else
{
int err = WSAGetLastError(); //当出现非接收超时的错误时打印错误号
if (err != 10060)
{
printf("recvfrom函数调用错误,错误号:%d\n", err);
iResult = -1;
}
else
{
iResult = 0;
break;
}
}
}
while (iResult > 0);
if (count > 0)
printf("服务器总共接收到%d个数据报\n", count);
return iResult;
}
2、int udp_client_fun_packetloss(int times, SOCKET s)
{
int iResult, i = 0;
char sendline[MAXLINE - 1000];
char recvtimes = 0;
memset(sendline, 1, MAXLINE - 1000); //根据用户输入的发送次数循环发送相同的数据报 printf("\r\n客户端发送%d次数据\r\n", times);
while (i < times)
{
iResult = send(s, sendline, strlen(sendline), 0);
if (iResult == SOCKET_ERROR)
{
printf("send 函数调用错误,错误号:%d\n", WSAGetLastError());
return -1;
}
i++; //printf("\r\n客户端发送%d次数据\r\n", i);
}
return iResult;
}
3、int udp_client_fun_packetloss(int times, SOCKET s, SOCKADDR * servaddr, int servlen)
{ int iResult, i = 0;
char sendline[MAXLINE - 1000];
char recvtimes = 0;
memset(sendline, 1, MAXLINE - 1000); //根据用户输入的发送次数循环发送相同的数据报
printf("\r\n客户端发送%d次数据\r\n", times);
while (i < times)
{
iResult = sendto(s, sendline, strlen(sendline), 0, (SOCKADDR *)servaddr, servlen);
if (iResult == SOCKET_ERROR)
{
printf("send 函数调用错误,错误号:%d\n", WSAGetLastError());
return -1;
}
i++; //printf("\r\n客户端发送%d次数据\r\n", i);
}
return iResult;
}
二、主函数
1、server.c
int main(int argc, char* argv[])
{ int iResult = 0;
SOCKET ServerSocket;
start_up();
ServerSocket = udp_server("127.0.0.1", ECHOPORT);
if (ServerSocket == -1)
return -1;
int rcvbuf_len;
int len = sizeof(rcvbuf_len);
if (getsockopt(ServerSocket, SOL_SOCKET, SO_RCVBUF, (char *)&rcvbuf_len, &len) < 0)
{
printf("getsockopt error\n");
return -1;
}
printf("系统接收缓存默认大小: %d\n", rcvbuf_len); //获得用户输入的系统缓存大小并设置
rcvbuf_len = atoi(argv[1]);
if (setsockopt(ServerSocket, SOL_SOCKET, SO_RCVBUF, (const char *)&rcvbuf_len, len) < 0)
{
printf("setsockopt error\n");
return -1;
}
printf("系统接收缓存被设置为: %d\n", rcvbuf_len); //设置套接字的接收超时时间
int nTimeOver = TIMEOVER;
if (setsockopt(ServerSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&nTimeOver, sizeof(nTimeOver)) < 0)
{
printf("setsockopt error\n");
return -1;
}
printf("系统接收超时时间被设置为:%d毫秒\n",nTimeOver);
printf("服务器准备好丢包率测试服务\n");
for (; ; )
{
iResult = udp_server_fun_packetloss(ServerSocket);
if (iResult == -1)
printf("当前测试出错\n");
}
quit(ServerSocket);
return iResult;
}
2、Clinet.c
int main(int argc, char *argv[])
{ int iResult = 0;
SOCKET ClientSocket;
sockaddr_in servaddr;
int times;
start_up();
ClientSocket = udp_client((char *)argv[1], ECHOPORT, true);
if (ClientSocket == -1)
return -1;
printf("客户端启动成功 \n");
if (set_address((char *)argv[1], ECHOPORT, &servaddr, "udp") == 1)
return 0;
times = atoi(argv[2]);
iResult = udp_client_fun_packetloss(times,ClientSocket, (SOCKADDR *)&servaddr, sizeof(sockaddr_in));
if (iResult == -1)
printf("当前测试出错!\n");
quit(ClientSocket); return iResult;
}