【问题标题】:why client connections appear as established when connection is not accepted yet为什么尚未接受连接时客户端连接显示为已建立
【发布时间】:2013-09-01 10:09:44
【问题描述】:

我试图重现服务器负载过重的情况,应该有一些状态为 SYN_SENT 的连接,通过 netcat 可视化。

我创建了一个服务器套接字并从 netcat 打开了十个连接;我以为它们会在 netstat 中显示为 SYN_SENT,但随后使用 tcpdump,看起来内核发送 syn-ack 并且客户端以 ack 响应并且 tcp 握手完成并且它们都已建立。

import java.io.IOException;
import java.net.ServerSocket;

public class Server {

    public static void main(String[] args) throws IOException, InterruptedException {
        ServerSocket ss = new ServerSocket(9999);
        Thread.currentThread().join();
    }
}

所以serversocket.accept 在连接建立中没有任何作用(决定是否应该发送syn.ack)而是等待操作系统/内核为该套接字分配一个io 句柄?这种行为在不同操作系统之间是否一致?

【问题讨论】:

    标签: java sockets serversocket linux-mint


    【解决方案1】:

    因为连接已建立。调用 accept() 不是先决条件。系统接受传入连接并将它们排入积压队列。调用 accept() 只是从队列中删除一个项目,当它为空时阻塞。

    【讨论】:

    • accept() 调用将积压工作作为参数。此输入确定允许的最大挂起 TCP 连接数。因此,如果您正在处理大量连接,请确保为 accept() 调用指定较大的积压限制。请注意,底层操作系统也可以有自己的限制。例如,Linux 有自己的最大连接数限制(我认为是 256),因此如果您指定的积压工作超过 256,那么 Linux 不会采用该连接数,而是使用 256 的最大限制。
    • @ManojPandey listen() 调用将积压作为参数。该平台可以改变您指定的内容,向上或向下,并且无法发现它是否这样做,或者有效值是多少。在我看来,这应该是问题的答案,而不是对此答案的评论。
    • 好吧,我首先喜欢你的回答(因此,赞成它!),所以我认为添加有关积压的详细信息将是你回答的一个很好的附加信息!。我同意,listen() 提供的最大限制可能令人惊讶,作为一名程序员,尤其是在编写连接密集型应用程序时,需要注意这一点。
    • 那是一个错字:你是对的,是 listen() 调用需要积压而不是 accept() .. 对于由于积压限制而被丢弃的连接,节省的恩典是TCP 旨在处理这个问题。当服务器因为达到 backlog 而忽略 SYN 时,它会简单地丢弃 SYN 数据包而不发送 RST——这样,客户端可以稍后重试并发送另一个 SYN。希望到那时,积压工作会减少。
    • @ManojPandey 这取决于平台。当积压已满时,Windows 会发送 RST。 Unix 和 Linux 的行为与您描述的一样。
    【解决方案2】:

    SYN_SENT 存在于网络堆栈的较低级别,而不是您在此处使用的级别。使用网络数据包制作工具来欺骗您需要的连接部分,您可能会获得更好的结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-20
      相关资源
      最近更新 更多