sendto丢包

sendto是udp发送报文的御用接口。他的函数原型如下:

cpp 复制代码
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);

在使用kvs的数据通道时发现sendto调用太频繁会导致丢包,而且返回值还与发送长度相等,没有一点报错的迹象。(给亚马逊点个点赞,他们对sendto的使用堪称教科书。先sendto而后poll)

于是自己写了一个sendto的测试用例,如下:

cpp 复制代码
  1 /*************************************************************************
  2 *File Name: udp_client.h
  3 *Author: Augus
  4 *email: augus@lockin.com
  5 *Created Time: 2025年01月25日 星期六 22时07分31秒
  6 *Describtion:
  7 ************************************************************************/
  8
  9 #ifndef __UDP_CLIENT_H__
 10 #define __UDP_CLIENT_H__
 11
 12 #include <unistd.h>
 13 #include <stdio.h>
 14 #include <stdlib.h>
 15 #include <sys/types.h>          /* See NOTES */
 16 #include <sys/socket.h>
 17 #include <arpa/inet.h>
 18 #include <fcntl.h>
 19 #include <netinet/in.h>
 20 #include <netinet/tcp.h>
 21 #include <string.h>
 22 #include <errno.h>
 23
 24 #define DBG(fmt, arg...) printf("{%s:%d} " fmt "\n", __func__, __LINE__, ##arg)
 25
 26 #endif
cpp 复制代码
  1 /*************************************************************************
  2 *File Name: udp_client.c
  3 *Author: Augus
  4 *email: augus@lockin.com
  5 *Created Time: 2025年01月25日 星期六 21时52分18秒
  6 *Describtion:
  7 ************************************************************************/
  8
  9 #include "udp_client.h"
 10
 11
 12 int main(){
 13     int32_t sockfd;
 14     int32_t ret;
 15     int32_t flags;
 16     int32_t count;
 17     struct sockaddr* destAddr = NULL;
 18     struct sockaddr_in ipv4Addr;
 19     int32_t addrLen;
 20     int32_t optionValue=0;
 21     int32_t bufsize=1048;
 22     char *buffer=malloc(bufsize);
 23     sockfd = socket(AF_INET, SOCK_DGRAM, 0);
 24
 25     flags = fcntl(sockfd, F_GETFL, 0);
 26     ret=fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
 27
 28     optionValue = 1;
 29     ret=setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &optionValue, sizeof(optionValue));
 30
 31     addrLen = sizeof(ipv4Addr);
 32     memset(&ipv4Addr, 0x00, sizeof(ipv4Addr));
 33     ipv4Addr.sin_family = AF_INET;
 34     ipv4Addr.sin_port = htons(1234);
 35     inet_pton(AF_INET,"192.168.31.207",&ipv4Addr.sin_addr);
 36     destAddr = (struct sockaddr*) &ipv4Addr;
 37     count=1000000;
 38     while(count--){
 39         ret = sendto(sockfd,buffer,bufsize,MSG_NOSIGNAL, destAddr, addrLen);
 40         if(ret!=bufsize){
 41             DBG("ret=%d,errno=%s",ret,strerror(errno));
 42         }
 43         //             //!< 不调用usleep时发送1m包丢失689505包,包间隔30us,----------------出现EGAIN,----iftop统计发送速率300sMbps
 44         //usleep(0);   //!< 延时0us发送1m包丢失1817包,---------包间隔不稳定:几十us到几百us,没有EAGAIN---iftop统计发送速率16.5Mbps
 45         //usleep(1);   //!< 延时1us发送1m包丢失1214包,---------包间隔300us,---------------没有EAGAIN,-----iftop统计发送速率16.2Mbps
 46         //usleep(10);  //!< 延时10us发送1m包丢失831包,---------包间隔400us,---------------没有EAGAIN,-----iftop统计发送速率16.0Mbps
 47         //usleep(100); //!< 延时100us发送1m包就会丢795包,------包间隔500us,---------------没有EAGAIN,iftop统计发送速率15Mbps
 48         //usleep(1000);//!< 延时1000us发送1w包就没有丢包了,----包间隔1.45ms,--------------没有EAGAIN,iftop统计发送速率5.6Mbps

 49     }
 50     close(sockfd);
 51     return 0;
 52 }

测试结果如下:

//!< 不调用usleep时发送1m包丢失689505包,包间隔30us,----------------出现EGAIN报错

//!< 延时0us发送1m包丢失1817包,---------包间隔不稳:几十到几百us,--没有EAGAIN

//!< 延时1us发送1m包丢失1214包,---------包间隔300us,-------------------没有EAGAIN

//!< 延时10us发送1m包丢失831包,---------包间隔400us,-------------------没有EAGAIN

//!< 延时100us发送1m包就会丢795包,------包间隔500us,-----------------没有EAGAIN

//!< 延时1000us发送1w包就没有丢包了,----包间隔1.45ms,---------------没有EAGAIN

通过上述测试分析,足以说明sendto丢包是确实存在的,而且丢包的地方有两个层级:

  1. ip协议栈udp缓存溢出,sendto会返回-1。
  2. 网卡驱动txqueue溢出,sendto返回正常。

https://groups.google.com/g/dev4server/c/2V3AiDJHhJIhttps://groups.google.com/g/dev4server/c/2V3AiDJHhJIhttps://groups.google.com/g/dev4server/c/2V3AiDJHhJI

相关推荐
程序猿小三1 小时前
Linux下基于关键词文件搜索
linux·运维·服务器
虚拟指尖1 小时前
Ubuntu编译安装COLMAP【实测编译成功】
linux·运维·ubuntu
刘某的Cloud2 小时前
parted磁盘管理
linux·运维·系统·parted
啊?啊?2 小时前
4 解锁 Linux 操作新姿势:man、grep、tar ,创建用户及添加权限等 10 大实用命令详解
linux·服务器·实用指令
程序员老舅2 小时前
干货|腾讯 Linux C/C++ 后端开发岗面试
linux·c语言·c++·编程·大厂面试题
爱倒腾的老唐3 小时前
24、Linux 路由管理
linux·运维·网络
程序员Aries3 小时前
自定义网络协议与序列化/反序列化
linux·网络·c++·网络协议·程序人生
泽02023 小时前
Linux之环境变量
java·linux·redis
正在努力的小河3 小时前
Linux 自带的 LED 灯驱动实验
linux·运维·服务器
檀越剑指大厂4 小时前
【Linux系列】Vim 中删除当前光标到行尾
linux·运维·vim