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: [email protected]
  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: [email protected]
  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 小时前
CentOS 系统升级失败的原因与排查
linux·运维·服务器
码哝小鱼1 小时前
系统间安全复制和同步文件
linux·服务器·安全
GottdesKrieges2 小时前
OceanBase性能关键参数配置最佳实践
linux·oceanbase
努力学习的小廉3 小时前
深入了解linux系统—— 自定义shell
linux·运维·chrome
孞㐑¥3 小时前
Linux之进程概念
linux·c++·经验分享·笔记
Lw老王要学习3 小时前
Linux架构篇、第三章_2_Linux服务器监控与NGINX优化
linux·运维·服务器·nginx·架构·云计算
极小狐3 小时前
如何从极狐GitLab 容器镜像库中删除容器镜像?
java·linux·开发语言·数据库·python·elasticsearch·gitlab
极小狐3 小时前
如何使用极狐GitLab 软件包仓库功能托管 terraform?
linux·运维·git·ssh·gitlab·terraform
mixboot3 小时前
CentOS 7.9 安装详解:手动分区完全指南
linux·centos·手动分区