在我有兴趣接受之前,我可以将套接字留在 SYN_RECV 中吗?

Posted

技术标签:

【中文标题】在我有兴趣接受之前,我可以将套接字留在 SYN_RECV 中吗?【英文标题】:Can I leave sockets in SYN_RECV until I'm interested in accepting? 【发布时间】:2016-05-08 14:35:20 【问题描述】:

在我写的torrent client 中,我不接受连接,除非我真的想要或需要更多连接。这导致netstat 显示很多SYN_RECV,这似乎是合理的,因为我还没有完成连接。这些会消耗服务器上可用的文件描述符吗?在我真正想要接受之前让积压工作填满是不好的做法吗?有更好的做法吗?

【问题讨论】:

【参考方案1】:

没有。连接由 TCP 堆栈完成,可能早在您调用 accept(), 并放入积压队列之前。 accept() 所做的只是在 backlog 队列为空时阻塞,然后将 head 元素作为套接字 FD 移除并返回。它与连接握手没有任何关系。

积压队列中的连接不消耗文件描述符。 FD由accept().分配

一般来说,您应该尽快处理积压队列。如果您从不接受积压队列中的连接,它最终会在您关闭侦听套接字时重置,这会使对等方感到困惑。与此同时,它一直在消耗对等端的一个套接字和一个线程,从而浪费了那里的资源。如果您不想要该连接,请接受它并关闭它。

特定平台上的 YMMV。

【讨论】:

我距离我的引用还有很长的路要走,直到明天,但我相信处于 SYN_RECV 状态的套接字处于另一个由于积压队列已满而无法完成的连接的优先队列中,并且我相信这个队列应该很快就会超时。但这都是因为不接受连接。 假设配置参数正常,将它们放在 backlog 中会以任何方式降低系统性能吗?如果系统在 accept 被调用之前就完成了握手,这真的还是 SYN_RECV 状态吗? @MattJoiner 通过不接受您正在消耗积压队列资源,并降低和误导客户。积压队列中的已完成连接当然处于 ESTABLISHED 状态。 SYN_RECV 是先验状态。我已经说过了。 这些连接肯定还在 SYN_RECV 中。我现在假设他们可能没有合法地完成握手,并且不会从 accept() 返回。 所以他们仍然在优先积压队列中。我们已经解决了。【参考方案2】:

有更好的做法吗?

如果您暂时不想接受处理其他连接,请接受并立即关闭它们。

但在 bittorrent 的上下文中,您可能希望改为实现 BEP 40,并至少执行一次 bittorrent 握手以查看连接属于哪个群以及是否应该放弃现有的连接以支持新连接并仅关闭如果您确定连接的优先级低于现有连接,则连接。

【讨论】:

谢谢。如果有任何可能我想使用它,我实际上接受它。例如,如果客户端上的所有种子都已完成,并且不被播种,我没有理由接受任何东西。那这个案子呢? 感谢 BEP40 的链接!我不知道这存在。 accept&close 是常用的方法。原则上你也可以关闭服务器套接字,但我认为很少有人会这样做。

以上是关于在我有兴趣接受之前,我可以将套接字留在 SYN_RECV 中吗?的主要内容,如果未能解决你的问题,请参考以下文章

JAVA套接字在接受数据之前关闭

开始使用 Web 套接字

在接受连接 C++ 之前获取套接字的 IP 地址

范围在我可以返回之前破坏值(RUST)

在使用Boost :: asio之前从套接字读取之后是否可以执行async_handshake?

Postgres 接受任何密码