【问题标题】:More TCP and POSIX sockets listen() and accept() semantics更多 TCP 和 POSIX 套接字 listen() 和 accept() 语义
【发布时间】:2010-10-18 22:36:21
【问题描述】:

情况:服务器调用listen()(但不是accept()!)。客户端向服务器发送一个 SYN。服务器获取 SYN,然后将 SYN/ACK 发送回客户端。但是,客户端现在挂起/死亡,因此它永远不会向服务器发送回 ACK。连接处于 SYN_SENT 状态。

现在另一个客户端发送一个 SYN,从服务器获取一个 SYN/ACK,然后发回一个 ACK​​。此连接现在处于 ESTABLISHED 状态。

现在服务器终于调用了accept()。发生什么了?在出现某种超时之前,accept() 是否会阻塞第一个错误连接?它是否首先检查队列中是否存在任何已建立的连接并返回这些连接?

【问题讨论】:

  • 当服务器获得 SYN 并返回 SYN/ACK 时,连接(从服务器角度)处于 SYN_RCVD 状态。是客户端处于 SYN_SENT 状态,与讨论无关。
  • 不,服务器发送 SYN/ACK 后,也是在 SYN_SENT 中。
  • 哦,抱歉 - 看来您是对的。我可能需要修复我的代码 - 谢谢!

标签: language-agnostic sockets network-programming tcp


【解决方案1】:

嗯,你在这里描述的是一个典型的 syn-flood 攻击 (http://en.wikipedia.org/wiki/SYN_flood),当多次执行时。

当查看示例时:http://lkml.indiana.edu/hypermail/linux/kernel/0307.0/1258.html 有两个单独的队列,一个同步队列和一个已建立的队列。显然,第一个连接将保留在同步队列中(因为它处于 SYN_RCVD 状态),第二个连接将在已建立的队列中,accept() 将从中获取它。 netstat 仍应显示第一个处于 SYN_RCVD 状态。

注意:另见我的评论,客户端将处于 SYN_SENT 状态,服务器(我们正在讨论)将处于 SYN_RCVD 状态。

【讨论】:

    【解决方案2】:

    您应该注意,在某些实现中,半开连接(处于 SYN_RCVD 状态的连接)甚至可能不会记录在服务器上。实现可以使用SYN cookies,其中他们将完成建立连接所需的所有信息编码为SYN+ACK数据包的序列号。当 ACK 包返回时,序列号递增,他们可以递减它并取回信息。这可以通过不在服务器上为这些半开连接分配任何资源来帮助防止 SYN 泛滥;因此无论客户端发送多少额外的SYN包,服务器都不会耗尽资源。

    请注意,SCTP 实现了 4 次握手,协议中内置了 cookie,以防止 SYN 泛滥,同时允许将更多信息存储在 cookie 中,因此不必限制支持的协议功能,因为cookie 的大小太小(在 TCP 中,您只能获得 32 位的序列号来存储所有信息)。

    所以要回答您的问题,用户空间 accept() 只会看到完全建立的连接,并且不会看到纯粹是 TCP 堆栈的实现细节的半开连接。

    【讨论】:

      【解决方案3】:

      您必须记住,listen()accept() 等都不是底层协议调试工具。从 accept 手册页:“接受 - 接受套接字上的连接”。不完整的连接不会被报告,也不应该被报告。应用程序无需担心套接字的设置和拆除、重传、片段重组或...

      如果您正在编写一个网络应用程序,那么涵盖您应该关心的事情就绰绰有余了。如果您有一个正在运行的应用程序但正在尝试找出问题,那么请使用一个不错的网络调试工具、用于检查您的操作系统状态的工具等。不要尝试将其放入您的应用程序中。

      如果您尝试编写调试工具,那么您无法通过使用应用程序级别的 TCP/IP 调用来完成您想要的工作。您需要至少下拉一级。

      【讨论】:

      • 我正在为一个项目自己实现listen()和accept(),所以我必须知道它们的行为方式。
      猜你喜欢
      • 2010-10-16
      • 2016-03-08
      • 2014-02-10
      • 1970-01-01
      • 2020-04-29
      • 2017-08-10
      • 1970-01-01
      • 2020-04-26
      • 1970-01-01
      相关资源
      最近更新 更多