gpt4 book ai didi

c - Linux 中 TCP 连接异常缓慢

转载 作者:行者123 更新时间:2023-12-04 12:36:13 24 4
gpt4 key购买 nike

我写了用户模式客户端 - 服务器 基于通过某些专用网络交互的 Berkeley 套接字的应用程序。
情况肯定很奇怪。有时,在某些模糊的情况下,连接会变得非常缓慢。在我的例子中,正常的 TCP 数据交换是每段大约 10-25 KB 的有效载荷,但有时它变成每段大约 200-500 字节。

经过一些故障排除后,我意识到这个问题对于其他网络服务是不可重现的,因此看起来应该归咎于我的服务。但我想不通,怎么了。它在 3.10 Linux 内核上运行良好,但在 4.4 上有这种奇怪的行为。是否是一些内部内核更改导致了此类问题?

我试着玩 Linux sysctl设置:

net.ipv4.tcp_congestion_control
net.ipv4.tcp_sack
net.ipv4.route.flush

但这没有帮助。

好像是 问题出现 在监听套接字端 .在 tcpdump握手时 TCP 窗口大小正常。但是在第一个传入数据包窗口大小减小后(在监听器方面)。

UPD
这是我的服务器端代码片段:
 serv_fd = socket(AF_INET, SOCK_STREAM, 0); 
if (serv_fd == -1) {
perror("socket");
return;
}

server.sin_family = AF_INET;
server.sin_port = htons(LISTEN_PORT);
server.sin_addr.s_addr = htonl(INADDR_ANY);

#ifdef SET_BUF
if (setsockopt(serv_fd, SOL_SOCKET, SO_RCVBUF, &buflen, sizeof(int)) == -1) {
perror ("setsockopt");
return;
}
if (setsockopt(serv_fd, SOL_SOCKET, SO_SNDBUF, &buflen, sizeof(int)) == -1) {
perror ("setsockopt");
return;
}
#endif // SET_BUF

if (bind(serv_fd, (struct sockaddr *) &server, sizeof(server)) == -1) {
perror("bind");
return;
}

if (listen(serv_fd, 3)) {
perror("listen");
return;
}

printf("Server is listening on %u\n", LISTEN_PORT);

有人可以对我的问题有所了解吗?我会很感激!
是否与最近的一些 Linux 内核修改有关?我是否需要调整一些 Linux 内核设置或检查一些用户模式设置(例如套接字选项或其他)?

附言问题不稳定。

更新:

tcpdump 的输出:
IP 10.0.0.34.31334 > 10.0.0.99.12345: Flags [S], seq 426261790, win 43690, options [mss 65495,sackOK,TS val 799180610 ecr 0,nop,wscale 7], length 0
IP 10.0.0.99.12345 > 10.0.0.34.31334: Flags [S.], seq 803872704, ack 426261791, win 65483, options [mss 65495,sackOK,TS val 799180567 ecr 799180610,nop,wscale 0], length 0
IP 10.0.0.34.31334 > 10.0.0.99.12345: Flags [.], ack 1, win 342, options [nop,nop,TS val 799180610 ecr 799180567], length 0
IP 10.0.0.34.31334 > 10.0.0.99.12345: Flags [P.], seq 1:1301, ack 1, win 342, options [nop,nop,TS val 799180610 ecr 799180567], length 1300
IP 10.0.0.34.31334 > 10.0.0.99.12345: Flags [P.], seq 1301:1804, ack 1, win 342, options [nop,nop,TS val 799181412 ecr 799180610], length 503
IP 10.0.0.99.12345 > 10.0.0.34.31334: Flags [.], ack 1804, win 512, options [nop,nop,TS val 799181412 ecr 799181412], length 0

10.0.0.34.31334 是客户端,10.0.0.99.12345 是服务器。注意意外 win 512在最后一行。

UPD2:
我在 dmesg 中看到了几条关于 SYN-cookies 的消息,例如:
possible SYN flooding on port 12345. Sending cookies.

但它们与慢速传输的时间关系不大。

最佳答案

我不确定这正是您的情况,但看起来很相似。好像是known problem .

原因

许多情况会导致这样的 Linux 内核行为:

  • 中内核连接处理的特殊性SYN-cookies 上下文 具有零窗口比例的连接(或者如果 WS 以其他方式修改)。
  • 零窗口比例 你激怒了setsockopt()SO_RCVBUF (见 tcp_select_initial_window() )
  • backlog


  • 解释

    关于“慢”传输:
    Windows Scaling option由两个主机在 [SYN - SYN+ACK] 阶段计算。粗略地说,主机 A 说“在 future 交换期间暗示我在 N 上的 TCP 窗口大小”(SYN)然后主机 B 说“在 future 交换期间暗示我在 M 上的 TCP 窗口大小”(SYN+ACK)——这里 N 和 M 可能相同.因此,在正常情况下,这些系数被存储并最终在数据交换时使用。
    但是 TCP SYN-cookies技术意味着忘记连接的 [SYN - SYN+ACK] 阶段(某些声明的选项,包括 WS 将在 SYN+ACK 后丢失)。在那种情况下 Linux 内核 重新计算 WS 值(value) 当 ACK 到达时 (如果 ACK 已到达,则需要创建常规连接)。但是第二次重新计算可能会有所不同,因为 setsockopt()不影响它(出于某些客观原因)。在这里,您面临的情况是,当您的服务器使用 SYN+ACK 发送零窗口缩放选项,然后忘记它,然后重新生成连接(当 ACK 到达时),就像使用某些默认窗口缩放(例如 7)一样并使用小窗口暗示客户端将其乘以 128。但客户端不会忘记 WS 是 0 并将小窗口大小视为真实的 - 因此它发送了一小部分数据 - 因此你的“慢”连接占据了舞台。

    关于SYN-flood:
    当您有这么小的积压时,简单的 3 次 SYN 重传就可以引发 SYN-cookie(即会填满您的积压队列)。顺便说一句,你在 tcpdump 中看到重传了吗?
    来自 ip-sysctl.txt :
    Note, that syncookies is fallback facility.
    It MUST NOT be used to help highly loaded servers to stand
    against legal connection rate. If you see SYN flood warnings
    in your logs, but investigation shows that they occur
    because of overload with legal connections, you should tune
    another parameters until this warning disappear.
    See: tcp_max_syn_backlog, tcp_synack_retries, tcp_abort_on_overflow.

    syncookies seriously violate TCP protocol, do not allow
    to use TCP extensions, can result in serious degradation
    of some services (f.e. SMTP relaying), visible not by you,
    but your clients and relays, contacting you. While you see
    SYN flood warnings in logs not being really flooded, your server
    is seriously misconfigured.

    因此,如果您的 LAN 中没有 SYN-flood 攻击 - 您的服务器配置严重错误。 SYN-cookies 应该只在出现 SYN-flood 攻击时才起作用。

    解决方案

    最后,可以有一些事件来消除这个问题:
  • 如果您的网络中存在真正的 SYN-flood - 部分 SYN-cookies
    解决这个信息安全问题。有了真正的攻击,
    没有时间考虑慢速连接。这是紧急情况。
  • 如果没有,即某些 SYN 重传引发了 SYN cookie:
  • thoughtfully increase backlog消除这些条件;
  • 不要做setsockopt()SO_RCVBUF监听套接字 .这没有多大意义。不做setsockopt()在上述场景中,您可以通过内核降低不同 WS 计算的概率。顺便说一句,您可以设置 SO_RCVBUF如果需要,在接受的套接字上。


  • 再现

    我用 hping3 用简单的客户端和服务器重现了您的问题在近似条件下。因此,您可以使用以下内容填充服务器的积压队列:
    hping3 -c 3 -S -p 12345 --fast 10.0.0.99

    然后从客户端启动连接 - 至少在 4.4 内核上,连接将在所谓的“SYN-cookies 上下文”中打开。您也可以在 3.10 内核增加 -c 上检查它来自 3X直至成功繁殖。

    关于c - Linux 中 TCP 连接异常缓慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59774872/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com