具有多个服务器的Java NIO UDP客户端
我正在构建一个UDP客户端,它可以与一系列不同的服务器进行通信。鉴于NIO应用程序涉及使用单个接收线程,如何将传入的数据报分派到应用程序的正确部分?i、 e.将传入数据包与传出数据包相关联 理论上,当发送(或连接?)到服务器时,应该可以在传出数据报中获取源ip/端口,然后通过检查目标ip/端口将传入数据包识别为其响应。(因为:) 大多数UDP客户机示例似乎假定为一台服务器,因此将传入数据报识别为对传出数据报的响应是很简单的,例如:具有多个服务器的Java NIO UDP客户端,java,udp,nio,Java,Udp,Nio,我正在构建一个UDP客户端,它可以与一系列不同的服务器进行通信。鉴于NIO应用程序涉及使用单个接收线程,如何将传入的数据报分派到应用程序的正确部分?i、 e.将传入数据包与传出数据包相关联 理论上,当发送(或连接?)到服务器时,应该可以在传出数据报中获取源ip/端口,然后通过检查目标ip/端口将传入数据包识别为其响应。(因为:) 大多数UDP客户机示例似乎假定为一台服务器,因此将传入数据报识别为对传出数据报的响应是很简单的,例如: ByteBuffer textToEcho = ByteBuff
ByteBuffer textToEcho = ByteBuffer.wrap("blah");
ByteBuffer echoedText = ByteBuffer.allocateDirect(MAX_PACKET_SIZE);
DatagramChannel datagramChannel = DatagramChannel.open(StandardProtocolFamily.INET)
datagramChannel.connect(new InetSocketAddress(REMOTE_IP, REMOTE_PORT));
while(true)
{
int sent = datagramChannel.write(textToEcho);
datagramChannel.read(echoedText);
}
也许我可以使用多个数据报通道,并对每个数据报通道迭代调用read(),将数据发送到我的应用程序需要响应的地方?您应该打开一个单独的数据报通道到希望与之通信的每台服务器,并移交该通道的管理(读/写)到一个单独的线程。如果只使用一个通道(和一个绑定的本地端口),则需要避免使用
connect
和write
方法。相反,请使用send
方法
send
方法。每次发送后,您可能需要倒带()
字节缓冲区。。。我不确定send
是否克隆了缓冲区
receive
获取返回的数据(缓冲区参数)和返回数据的服务器(方法返回值)。继续循环,直到服务器列表耗尽,但您希望对循环本身设置时间限制(对于死机服务器或丢失的数据包)理想情况下,在接收循环中,您希望接收方法在超时之前阻塞一小段时间。如果找不到配置阻塞的方法,可以使用非阻塞,并将Thread.sleep放在循环中。尝试让定时阻塞工作,这是最好的方法。那么在这种情况下,客户端上的每台服务器将有一个线程?我应该补充一点,客户机实际上是一台服务器,代表客户机将消息中继到另一台本地服务器。考虑到将有许多(实际的、非本地的)客户端,如果可能的话,我希望避免每个客户端都有一个线程。或者你的意思是我可以有专用的读写线程发送到多个通道。我对NIO风格编程的印象是,我们通常使用单个数据通道,但不知何故使用多路复用。我知道如何在发送时进行多路复用(只需指定目标ip:port),但我不知道如何在使用单个DatagramChannel的客户端上进行接收时进行多路复用,这正是我想要了解的。如果您真的只需要一个通道,那么是的:一个线程就是最好的选择。一个通道意味着一个端口,因此您必须检查传入的数据包源地址以区分服务器。我将添加另一个答案来解释如何。一个通道=一个端口,好吧,我没有意识到这一点,这是有意义的。尽管如此,即使我使用多个通道进行发送,从理论上讲,使用一个通道接收多个端口上的所有响应并将其多路传输也是可能的吗?我想我明白你的意思,但我在这方面的知识还存在差距。。。我知道我可以通过检查receive()返回的ip地址来识别哪个服务器返回数据,因为ip地址对于服务器是唯一的。但也可能有多个“流”从我的客户机流向同一台服务器。在这种情况下,我的应用程序(客户机)肯定需要知道传出端口的源ip和端口,以便能够适当地多路传输响应?假设这是正确的方法,我如何获得源ip?为什么需要源ip?您的客户端通道绑定到IP和端口,发送到该IP和端口的任何内容都将由您的通道拾取。您在该通道上发送和接收的所有内容都使用相同的IP和端口,因此即使您可以读取传入的目的地信息包,它也将始终是相同的。UDP中没有任何内容可以帮助区分与同一服务器的多个对话。您需要自己将这些信息包括在有效负载中:制定您自己的协议。听起来TCP更适合您所做的事情。“UDP中没有任何东西可以帮助您区分与同一服务器的多个对话。”但我认为,按照惯例,传出的数据包有一个源端口,它们的响应返回的端口与目标端口相同(如图所示:)。这肯定是DatagramChannel.connect()所做的用于接收适当的响应数据包?理论上可能是这样,但java没有提供这样做的方法。@user1478842是的,UDP端口可以区分。但是单个DatagramChannel只能在单个端口上发送/接收。如果要使用UDP端口区分服务器,则需要多个数据报通道(每个服务器/本地端口一个)。这是我推荐的方法。