【问题标题】:Is the SocketChannel returned by ServerSocketChannel.accept() guaranteed to be connected?ServerSocketChannel.accept()返回的SocketChannel是否保证连接?
【发布时间】:2016-08-07 05:23:27
【问题描述】:

这是一个非常基本的问题,但我在任何地方都找不到明确的答案:

当我accept() 来自 ServerSocketChannel 的连接时,我是否保证返回的 SocketChannel 是“connected”,或者返回的通道是否仍在执行某种形式的握手或其他任何形式,并且只会在以后设置它的SelectionKey.OP_CONNECT 位?

换句话说,我是否保证以下代码将永远打印 false

ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(1234));
SocketChannel socketChannel = serverSocketChannel.accept();
System.out.println(socketChannel.isConnected());

【问题讨论】:

  • 如果此通道处于非阻塞模式,则如果没有挂起的连接,此方法将立即返回 null。否则它将无限期阻塞,直到有新的连接可用或发生 I/O 错误。 似乎表明它将被连接。
  • @SotiriosDelimanolis “似乎”正是问题所在! ;) 在完全“连接”之前,连接可能已经被认为是“可用的”。也许......我不知道......我希望他们对此更清楚......

标签: java nio socketchannel


【解决方案1】:

根据ServerSocketChannelImpl 的来源ServerSocketChannelImpl 创建一个状态为ST_CONNECTED 的SocketChannelImpl

由于SocketChannelImpl.isConnected() 方法检查ST_CONNECTED 状态,因此您的测试应始终返回true。

然而,这是美好时光的场景。可能发生的情况是您的服务器线程被延迟,当您的线程调用 isConnected() 时,客户端已经关闭了连接。

所以,不,不能保证您的代码永远不会打印错误。

【讨论】:

    【解决方案2】:

    SocketChannel 的状态和底层套接字是独立的,直到通过读/写操作同步。 不保证在调用accept() 后套接字仍然打开。

    所以基本上,SocketChannel.isConnected() 在调用accept() 之后总是会返回TRUE,但这本质上是一个猜测。这还真不知道!对此进行测试的唯一方法是尝试将一些数据读/写到SocketChannel

    将数据写入通道将显示远程计算机上的套接字是否仍然打开。您可以通过使用交换机连接客户端和服务器然后移除其中一台计算机的网络电缆来测试此行为。您将看到套接字如何长时间保持打开状态。有一些套接字选项可以用来缓解这种情况,但效果不大。

    SocketChannel 读取只会在read() 返回-1 时显示它已关闭;

    【讨论】:

    • 这应该是公认的答案。 Oracle Java 8 绝对可以做到这一点。
    猜你喜欢
    • 2013-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-16
    • 1970-01-01
    • 1970-01-01
    • 2012-02-02
    • 1970-01-01
    相关资源
    最近更新 更多