udp丢包情况:
1.连续发送数据包太快 (每发一包数据usleep(40));
2.发送数据包太长 (数据进行切割成1400byte发送);
3.接收端处理时间过长导致丢包:调用recv方法接收端收到数据 后,处理数据花了一些时间,处理完后再次调用recv方法,
在这二次调用间隔里,发过来的包可能丢失。对于这种情况可以修改接收端,将包接收后存入一个缓冲区,然后迅速返回继续recv。
4.发送的包较大,超过接受者缓存导致丢包:包超过mtu size数倍,几个大的udp包可能会超过接收者的缓冲,导致丢包。
这种情况可以设置socket接收缓冲。以前遇到过这种问题,我把接收缓冲设置成64K就解决了。

Socket缓冲区大小修改与系统设置:(每个Socket在Linux中都映射为一个文件,并与内核中两个缓冲区(读缓冲区、写缓冲区)相关联。或者说,每个Socket拥有两个内核缓冲区。有时,我们需要修改缓冲区的内核限制的最大值,使其符合我们的实际需求)
cat /proc/sys/net/core/rmem_max 212992
rmem_max:一个Socket的读缓冲区可由程序设置的最大值,单位字节;
wmem_max:一个Socket的写缓冲区可由程序设置的最大值,单位字节;
rmem_default:一个Socket的被创建出来时,默认的读缓冲区大小,单位字节;
wmem_default:一个Socket的被创建出来时,默认的写缓冲区大小,单位字节;

应用程序级修改缓冲区大小
我们可以在程序中动态地修改(通过setsockopt系统调用)持有的有效Socket的读写缓冲区大小。

复制代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>

int main(int argc, char **argv)
{
if (argc != 2)
{
printf("Usage: %s $RCFBUFSIZE
", argv[0]);
goto error;
}

int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
printf("create socket error=%d(%s)!!!
", errno, strerror(errno));
goto error;
}

// 查看系统默认的socket接收缓冲区大小
int defRcvBufSize = -1;
socklen_t optlen = sizeof(defRcvBufSize);
if (getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &defRcvBufSize, &optlen) < 0)
{
printf("getsockopt error=%d(%s)!!!
", errno, strerror(errno));
goto error;
}
printf("OS default udp socket recv buff size is: %d
", defRcvBufSize);

// 按照执行参数设置UDP SOCKET接收缓冲区大小
int rcvBufSize = atoi(argv[1]);
if (rcvBufSize <= 0)
{
printf("rcvBufSize(%d) <= 0, error!!!
", rcvBufSize);
goto error;
}
printf("you want to set udp socket recv buff size to %d
", rcvBufSize);
optlen = sizeof(rcvBufSize);
if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &rcvBufSize, optlen) < 0)
{
printf("setsockopt error=%d(%s)!!!
", errno, strerror(errno));
goto error;
}
printf("set udp socket(%d) recv buff size to %d OK!!!
", sockfd, rcvBufSize);

// 查看当前UDP SOCKET接收缓冲区大小
int curRcvBufSize = -1;
optlen = sizeof(curRcvBufSize);
if (getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &curRcvBufSize, &optlen) < 0)
{
printf("getsockopt error=%d(%s)!!!
", errno, strerror(errno));
goto error;
}
printf("OS current udp socket(%d) recv buff size is: %d
", curRcvBufSize);

close(sockfd);

exit(0);

error:
if (sockfd >= 0)
close(sockfd);
exit(1);
}