我正在为我的项目重新编写核心NIO服务器网络代码,并且试图找出何时应“存储”连接信息以供将来使用。例如,一旦客户端以通常的方式连接,我就会为该连接客户端存储并关联SocketChannel对象,以便随时向该客户端写入数据。通常,我使用客户端的IP地址(包括端口)作为映射到SocketChannel对象的HashMap中的键。这样,我可以轻松地查询他们的IP地址,并通过该SocketChannel异步地向他们发送数据。Java NIO:OP_ACCEPT和OP_READ之间的关系?
这可能不是最好的方法,但它可以工作,并且该项目太大而无法更改其基本网络代码,但我会考虑建议。然而,我的主要问题是:
在什么时候我应该“存储”SocketChannel以供将来使用?一旦连接被接受(通过OP_ACCEPT),我一直在存储对SocketChannel的引用。我觉得这是一个有效的方法,因为我可以假设在OP_READ事件进入时映射条目已经存在。否则,每次发生OP_READ时,我都需要对HashMap进行计算量大的检查,并且很明显,对于客户端来说,这些会比OP_ACCEPT多得多。我猜,我担心可能会有一些连接被接受(OP_ACCEPT),但从不发送任何数据(OP_READ)。也许这可能是由于防火墙问题或故障客户端或网络适配器。我认为这可能会导致“僵尸”连接不活跃,但也永远不会收到关闭消息。
我重写网络代码的部分原因是,在极少数情况下,我得到的客户端连接已进入一种奇怪的状态。我正在考虑处理OP_ACCEPT和OP_READ的方式,包括我用来假设连接“有效”并可以存储的信息,可能是错误的。
对不起,我的问题不是更具体,我只是寻找最好的,最有效的方式来确定一个SocketChannel是否真正有效,所以我可以存储对它的引用。非常感谢您的帮助!
哇,感谢大量(和质量)的帮助!我正在研究这个东西,尽我所能。 - 我想你的意思是SocketChannel.register(),而不是SelectionKey.register(),对不对? - 我似乎可以通过仅为我的NIO使用一个线程来避免一些线程问题,对吧? - 定期检查应关闭的候选人的TIME_WAIT状态套接字是否合理? (你提到的半封闭问题) 非常感谢! – DivideByHero 2009-07-28 15:00:24
1)是的,register()在SelectableChannel上(SocketChannel扩展)。这就是我的意思。 2)您只能使用一个线程进行选择,然后关闭通道以进行读取/写入操作。如果你正在处理很多并发连接,你会发现一个线程本身跟不上。这是棘手的交接。 3)定期寻找半封闭的套接字已为我工作。 – mtnygard 2009-07-28 20:38:17