You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux系统下UDP发送缓冲区的正确配置方法

问题描述
  • 在Ubuntu 22.04.1 LTS环境下的C++程序中,发送大量小于1KB的UDP消息时,多数请求耗时低于300毫秒,但每约150次发送会出现一次3秒的延迟;该现象仅在WiFi网络中出现,以太网环境下无异常。
  • 尝试调整Linux系统参数net.core.rmem_max和net.core.rmem_default至26214400,未对程序产生任何影响。
  • 随后在代码中调用setsockopt(sock_fd, SOL_SOCKET, SO_SNDBUF, &size, size_len)设置发送缓冲区大小为26214400,延迟问题得以解决,但通过getsockopt查询发现实际生效的缓冲区大小为5228800。
  • 咨询:Linux下正确增大UDP发送缓冲区的方法是什么?
解决方案与细节解释

1. 纠正参数调整的错误方向

你之前修改的net.core.rmem_max和net.core.rmem_default是接收缓冲区的系统配置参数,和发送端延迟问题完全不相关,自然不会有效果。要调整UDP发送缓冲区,需要修改发送方向的系统参数:net.core.wmem_max(发送缓冲区最大上限)和net.core.wmem_default(默认发送缓冲区大小)。

2. 系统参数的正确调整方式

临时生效(重启系统后失效)

直接在终端执行以下命令:

sysctl -w net.core.wmem_max=26214400
sysctl -w net.core.wmem_default=26214400

永久生效(无需重启立即生效)

编辑/etc/sysctl.conf文件,添加或修改以下两行:

net.core.wmem_max=26214400
net.core.wmem_default=26214400

执行sysctl -p命令让配置立即生效。

3. 为什么代码设置的缓冲区大小和实际生效值不一致?

Linux内核会对应用层设置的SO_SNDBUF值做两层限制:

  • 内核会为自身管理预留额外空间,实际分配的缓冲区大小会和应用层请求值有差异(通常是内核内部做了对齐或资源预留处理)。
  • 如果你设置的SO_SNDBUF值超过了net.core.wmem_max,内核会自动截断到wmem_max允许的最大值(你之前未调整wmem_max,所以实际生效的5228800就是当时系统允许的最大发送缓冲区,刚好能解决你的延迟问题)。

如果想要让实际生效值更接近你的预期,先把net.core.wmem_max调整到足够大的数值(比如设置为52428800),再在代码中设置SO_SNDBUF。

4. 代码层面的正确设置步骤

在UDP socket创建完成后、绑定/发送数据之前,调用setsockopt设置发送缓冲区,示例代码如下:

#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main() {
    int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock_fd < 0) {
        perror("socket创建失败");
        exit(EXIT_FAILURE);
    }

    // 设置UDP发送缓冲区大小
    int send_buf_size = 26214400;
    socklen_t size_len = sizeof(send_buf_size);
    if (setsockopt(sock_fd, SOL_SOCKET, SO_SNDBUF, &send_buf_size, size_len) < 0) {
        perror("设置SO_SNDBUF失败");
        close(sock_fd);
        exit(EXIT_FAILURE);
    }

    // 验证实际生效的缓冲区大小
    int actual_size;
    getsockopt(sock_fd, SOL_SOCKET, SO_SNDBUF, &actual_size, &size_len);
    printf("实际UDP发送缓冲区大小: %d 字节\n", actual_size);

    // 后续的socket绑定、发送逻辑...

    close(sock_fd);
    return 0;
}

注意:必须在socket创建后立即设置缓冲区,不要等到绑定或发送数据后再操作,否则设置可能不生效。

5. WiFi环境下延迟的根源

WiFi属于共享无线介质,丢包率、传输稳定性远低于以太网。当UDP发送缓冲区满时,默认情况下sendto调用会阻塞,直到内核缓冲区有空闲空间。你之前的缓冲区太小,每发送约150个包就会填满缓冲区,导致阻塞等待;增大缓冲区后,能容纳更多待发送的数据包,避免了频繁的阻塞,从而消除了延迟。

内容的提问来源于stack exchange,提问作者immutableT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 14:05:31