sendto丢包

发布于:2025-02-10 ⋅ 阅读:(52) ⋅ 点赞:(0)

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

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的测试用例,如下:

  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
  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返回正常。

2025/02/07

尝试修改socket为阻塞模式

ret=fcntl(sockfd, F_SETFL, flags &(~O_NONBLOCK));

丢包结果和之前的差不多,但是:

  1. EAGIN的错误没有了,说明阻塞模式仅限于ip协议栈的阻塞而不是驱动层的阻塞
  2. 驱动丢包还是会有的,说明驱动队列还是会有丢包。

2025/02/08

尝试修改发送为send接口

/*************************************************************************
*File Name: udp_send.c
*Author: Augus
*email: augus@lockin.com
*Created Time: 2025年02月08日 星期六 10时18分30秒
*Describtion:
************************************************************************/

#include "udp_send.h"

int main(){
    int32_t sockfd;
    int32_t ret;
    int32_t flags;
    int32_t count;
    struct sockaddr* destAddr = NULL;
    struct sockaddr_in ipv4Addr;
    int32_t addrLen;
    int32_t optionValue=0;
    int32_t bufsize=1048;
    char *buffer=malloc(bufsize);
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    flags = fcntl(sockfd, F_GETFL, 0);
    ret=fcntl(sockfd, F_SETFL, flags &(~O_NONBLOCK));

    optionValue = 1;
    ret=setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &optionValue, sizeof(optionValue));

    addrLen = sizeof(ipv4Addr);
    memset(&ipv4Addr, 0x00, sizeof(ipv4Addr));
    ipv4Addr.sin_family = AF_INET;
    ipv4Addr.sin_port = htons(1234);
    inet_pton(AF_INET,"192.168.31.207",&ipv4Addr.sin_addr);
    destAddr = (struct sockaddr*) &ipv4Addr;

    connect(sockfd,destAddr,sizeof(*destAddr));
    count=1000000;
    while(count--){
        ret = send(sockfd,buffer,bufsize,0);
        if(ret!=bufsize){
            DBG("ret=%d,errno=%s",ret,strerror(errno));
        }
                     //!< 不调用usleep时发送1m包丢失689505包,包间隔30us,----------------出现EGAIN,----iftop统计发送速率300sMbps
        //usleep(0);   //!< 延时0us发送1m包丢失1817包,---------包间隔不稳定:几十us到几百us,没有EAGAIN---iftop统计发送速率16.5Mbps
        //usleep(1);   //!< 延时1us发送1m包丢失1214包,---------包间隔300us,---------------没有EAGAIN,-----iftop统计发送速率16.2Mbps
        //usleep(10);  //!< 延时10us发送1m包丢失831包,---------包间隔400us,---------------没有EAGAIN,-----iftop统计发送速率16.0Mbps
        //usleep(100); //!< 延时100us发送1m包就会丢795包,------包间隔500us,---------------没有EAGAIN,iftop统计发送速率15Mbps
        //usleep(1000);//!< 延时1000us发送1w包就没有丢包了,----包间隔1.45ms,--------------没有EAGAIN,iftop统计发送速率5.6Mbps
    }
    close(sockfd);
    return 0;
}

丢包结果甚至比起之前的会更严重哈哈🤣

接收端服务器

$ nc -l -u 1234 >log

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


网站公告

今日签到

点亮在社区的每一天
去签到