简体   繁体   English

java.nio的非阻塞选择问题

[英]Problems with non-blocking select with java.nio

I've just started using java.nio and probably used it some wrong way so I got a slight problem with it. 我刚刚开始使用java.nio,并且可能以错误的方式使用了它,因此我遇到了一个小问题。

I'm trying to write a something like a Port Forwarder that can modify the traffic that passes through it using various additional modules. 我正在尝试编写类似于端口转发器的东西,它可以使用各种其他模块来修改通过它的流量。

Here is how I'm doing it: 这是我的做法:

  1. ConnectionManager - a thread that has it's own Selector that is registered to OP_ACCEPT on ServerSocketChannel. ConnectionManager-具有它自己的选择器的线程,该线程在ServerSocketChannel上注册到OP_ACCEPT。 Whenever it selects anything - it creates a ConnectionProcessor object that manages the connection. 每当选择任何内容时,它都会创建一个ConnectionProcessor对象来管理连接。

  2. ConnectionProcessor - a thread that opens SocketChannel to predefined forward point (where to send the packets from the newly connected client). ConnectionProcessor-一个将SocketChannel打开到预定义的转发点(从新连接的客户端发送数据包的位置)的线程。 Then it opens it's own Selector and registers it to client's SocketChannel's OP_READ and server's SocketChannel's OP_READ. 然后,它打开它自己的选择器,并将其注册到客户端的SocketChannel的OP_READ和服务器的SocketChannel的OP_READ。

Then the processor goes into infinite loop selecting data from selector and forwarding it appropriately. 然后,处理器进入无限循环,从选择器中选择数据并适当转发。 To determine where to send data it compares SelectionKey.channel() to clientChannel and serverChannel. 为了确定将数据发送到何处,它将SelectionKey.channel()与clientChannel和serverChannel进行比较。

Selection in ConnectionProcessor is made with timeout of 5 seconds (select(5000)) - to handle timeouts. 在ConnectionProcessor中进行选择时需要5秒钟的超时时间(select(5000))-处理超时。 When select times out - it tries to read from both channels to get an exception or -1 result. 当select超时时-它尝试从两个通道读取以获取异常或-1结果。

Now here are my questions/problems: 现在这是我的问题/问题:

  1. Is it right to use key.cancel() after processing the key? 处理密钥后使用key.cancel()是否正确? Most examples I've seen in the internet simply remove the key from selectedKeys() list. 我在互联网上看到的大多数示例都只是从selectedKeys()列表中删除了密钥。 key.cancel() seems to be much better approach. key.cancel()似乎是更好的方法。
  2. Is it right to have several selectors that basically use the same ServerSocketChannel? 拥有几个基本上使用相同ServerSocketChannel的选择器是否正确? Or should I always use single Selector and pass selected keys to appropriate Managers? 还是我应该始终使用单个选择器并将选定的密钥传递给适当的管理员? What I mean is that if 3 clients connect simultaneously then this is what will happen: 我的意思是,如果3个客户端同时连接,则将发生以下情况:

    a) Manager creates Processor. a)经理创建处理器。 Processor opens client channel. 处理器打开客户端通道。 Processor registers it's own selector to the client channel. 处理器将其自己的选择器注册到客户端通道。 b) repetition of (a) c) repetition of (a) b)重复(a)c)重复(a)

  3. For some reason, after even one client connects to my forwarder - it won't process messages faster than 5000msec timeout. 由于某种原因,即使有一个客户端连接到我的转发器后,它也不会处理超过5000毫秒超时的消息。 It starts selecting, locks for 5 seconds, then go to second iteration and fetches me 5-6 messages that I received during previous timeout. 它开始选择,锁定5秒钟,然后进行第二次迭代,并获取我在上一个超时期间收到的5-6条消息。 Should I blame (1), (2), or some other reason? 我应该责怪(1),(2)还是其他原因?
  4. Is there any manual on how this all nio stuff works internally? 关于这一切的内部运作方式,是否有任何手册? I'm kind of a person that understands how to use things only after I fully understand the mechanics underneath. 我是一个只有在我充分了解底层机制之后才知道如何使用事物的人。 Reading API does not help as it is written for people who already know the proper way of using nio. 阅读API没有帮助,因为它是为已经知道使用nio正确方法的人编写的。

Thanks for reading my whole question and thanks in advance for any help. 感谢您阅读我的整个问题,并感谢您的任何帮助。

  1. No. Just remove the key from the selected set. 否。只需从所选集合中删除密钥即可。 Usually this is done via iterator.remove(). 通常,这是通过iterator.remove()完成的。 If you cancel they key it will never be selected again. 如果您取消它们的键,它将不再被选择。

  2. It's pointless. 没有用。 You don't need the second selector, or the extra thread either. 您不需要第二个选择器,也不需要额外的线程。 That's what NIO is for. 这就是NIO的目的。 You can handle it all with the original selector within the original thread. 您可以使用原始线程中的原始选择器来处理所有这些。

  3. It's probably caused by strange code. 这可能是由奇怪的代码引起的。 Redo it as above and see if it still happens. 如上重做它,看看它是否仍然发生。 If so, post some code here. 如果是这样,请在此处发布一些代码。

  4. You would need to read the Berkeley Sockets API or a good book such as Stevens, Unix Network Programming, or mine ;-) 您需要阅读Berkeley Sockets API或一本好书,例如Stevens,Unix Network Programming或我的;-)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM