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

相关推荐
HackTwoHub14 分钟前
最新Nessus2026.6.8版本主机漏洞扫描/探测工具Windows/Linux
linux·运维·服务器·安全·web安全·网络安全·安全架构
qq_1631357517 分钟前
Linux 【04-mkdir命令超详细教程】
linux
qq_1631357522 分钟前
Linux 【08-mv命令超详细教程】
linux
qq_163135753 小时前
Linux 【07-rm命令超详细教程】
linux
zh路西法4 小时前
【SSH 免密登录全流程】Windows Linux 通用方案
linux·windows·ssh
ScilogyHunter4 小时前
GCC完全指南
linux·gcc
CodeStats4 小时前
从 CPU 指令到 JVM 进程:彻底讲透 Java 执行 main 方法时,类加载、主线程、栈帧入栈的完整底层逻辑
java·linux·开发语言
努力努力再努力wz6 小时前
【内存管理与高并发内存池系列】从 mmap 到 malloc:文件映射、匿名映射与 glibc 内存分配机制详解
linux·c语言·数据结构·数据库·c++·qt·链表
Jurio.7 小时前
开源 Codex Sticky:在终端 Codex CLI 长对话中始终固定底部输入框
linux·rust·github·开源软件·codex·codex cli
无足鸟ICT7 小时前
【RHCA+】撤销和恢复撤销快捷键
linux