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

相关推荐
HLC++34 分钟前
Linux的进程间通信
android·linux·服务器
groundhappy4 小时前
idalib安装和codex ida-mcp配置
linux·开发语言·python
通信小小昕5 小时前
Ubuntu 26.04 中文输入法安装
linux·运维·ubuntu
张小姐的猫6 小时前
【Linux】网络编程 —— HTTP协议(上)
linux·运维·服务器·网络·http·单例模式·策略模式
栩栩云生7 小时前
AI 写代码犯的错,早被写进了错题集
linux·安全·ai编程
imc.118 小时前
linux基础IO
linux·运维·服务器
BelongPanda10 小时前
Linux Nginx 纯手动 Let‘s Encrypt 泛域名证书配置教程
linux·nginx
酷可达拉斯10 小时前
Linux操作系统-shell编程(0)
linux·运维·服务器·python·云计算
2301_7779983410 小时前
Linux中断机制:操作系统如何高效运行
linux·运维·服务器
yunwei3710 小时前
eBPF 教程:检查 exec 后真正安装的可执行镜像
linux·开源