0

这是一个课堂作业,所以我需要提示而不是答案。

我有一个在四台虚拟 linux 机器上运行的进程。每个进程与它的两个邻居进行通信。每个进程使用

server = ServerSocketChannel.open()
server.configureBlocking(false)
server.socket().bind(new InetSocketAddress(port))
server.register(selector, SelectionKey.OP_ACCEPT)

在启动时,进程 A 不会尝试连接到任何人。过程 B 确实

SocketChannel SC = SocketChannel.open()
SC.configureBlocking( false )
SC.connect(new INetSocketAddress( A-machine, A-port )
SC.register( selector, SC.validOps())

过程 C 对 B 做同样的事情;和 D 与 C。

接下来,我调用 selector.select 并遍历任何 selectedKeys。当我看到 key.isValid() && key.isAcceptable() 都为真时,我认为一个套接字正在尝试连接到我,我打电话

SocketChannel client = server.accept()
client.configureBlocking(false)
client.register(selector, client.validOps() )

当我看到 key.isValid() && key.isConnectable() 都为真时,我认为有一个服务器可供我连接。我打电话

SocketChannel connectingChannel = (SocketChannel)key.channel()
connectingChannel.finishConnect()

当我看到 key.isValid() && key.isReadable() 时,我读到了我收到的一条消息。

只要我按顺序启动进程:A、B、C、D,这个进程就可以工作。如果我只启动 B,它会在 finishConnect 语句中失败。

我阅读了文档,其中 isConnectable 测试此密钥的通道是否已完成或未能完成其套接字连接操作。isConnectable 怎么可能是真的,而我在 finishConnect 上失败了?

4

1 回答 1

0

我们在finishConnect 周围包裹了一个try/catch。在 catch 中,我们在当前的 SelectionKey 上调用了 cancel,然后调用了尝试连接的方法(原始问题描述中的第二个片段):

SocketChannel SC = SocketChannel.open()
SC.configureBlocking( false )
SC.connect(new INetSocketAddress( A-machine, A-port )
SC.register( selector, SC.validOps())

预计我们必须这样做,我们添加了代码来存储 SC 与 A 机器和 A 端口之间的关系,因此我们在重试时会拥有它们。因此,在 catch 中,在取消之前,我们使用失败的 SocketChannel 来查找我们将需要的必要的 A 机器和 A 端口数据。

最终,然后,服务器出现并成功建立了此连接。

我知道这是一个答案,而不是一个提示,但这是我们的任务 :)

于 2011-02-27T05:31:54.810 回答