5

我有一个基于 UDP Netty 的服务器。它有一个SimpleChannelUpstreamHandler流水线,我在其中覆盖该messageReceived方法。

我需要不时写回一些信息。我只能通过使用来自 的套接字信息MessageEvent.getRemoteAddress()和来自 的通道来做到这一点MessageEvent.getChannel()。为了能够重用这些信息,我将其保存在静态地图中。

这变成MessageEvent.getChannel().write("foo", MessageEvent.getRemoteAddress());

我本来期望的是有MessageEvent.getChannel().getRemoteAddress()工作,但事实并非如此。它总是给我null

  1. 难道我做错了什么 ?
  2. 有没有比在某些成员中保留频道和远程地址更好的回信方式?
4

3 回答 3

5

当使用 UDP(数据报)通道作为服务器通道时,您只需将其绑定到本地地址,并且不会建立连接。这就是为什么没有与通道相关联的远程地址并且您null在调用时总是得到的原因MessageEvent.getChannel().getRemoteAddress()。这种行为是预期的并且是正确的。同一个 UDP“服务器”通道处理所有传入的客户端请求。

当使用 UDP 通道作为客户端通道时,可以通过将通道连接到远程地址来创建“连接”。在这种情况下,通道将具有配置的远程地址(尽管没有建立实际连接)并且调用MessageEvent.getChannel().getRemoteAddress()将返回配置的远程地址。连接 UDP 通道可防止用户使用该通道向远程地址发送数据,而不是在通道上配置的地址。尝试这样做会引发异常。在 UDP 中连接客户端通道是可选的,只要保存了远程地址,客户端就可以使用仅绑定在本地地址上的通道正常操作。

我认为你有两个选择:

  1. 使用客户端标识符保存客户端远程地址并使用“服务器”通道发送数据。保存通道将不起作用,因为同一通道将用于与所有客户端进行通信。
  2. 为每个客户端创建一个新的连接通道,并使用客户端标识符保存新通道。

我相信第一个选项更好。

于 2013-07-05T15:19:29.650 回答
2

您可能知道 UDP 是一种无连接传输。单个通道可以从任何目标地址接收数据并将数据写入任何目标地址。因此,UDP 通道不像 TCP 通道那样具有关联的远程地址。虽然我认为可以让 netty 将 UDP 通道与特定的远程地址相关联,但我没有手头的详细信息,老实说,我认为从消息事件中获取地址是更好的选择。

这导致了您的第二个问题,是的,您需要将远程地址保存在某个地方。我没有在 Netty 中进行任何 UDP 编程,所以我不确定您是否需要将远程地址映射到通道对象,或者 Netty 是否总是返回相同的通道对象。值得检查一下,因为您可能只需要保留一个对频道的引用。

于 2013-06-27T08:18:06.900 回答
2

1) 看看这个UDP 上游处理程序。要获取发送者的远程地址,您可以使用以下代码SocketAddress remoteAddress = datagramPacket.sender();
2)@johnstlr 提到的是正确的,将 UDP 通道与单个远程地址相关联是不正确的。但是您可以使用并发 hashmap 进行查找,如上述文件所示。该游戏服务器实际上使用具有 TCP 和 UDP 连接的会话。这使得通过 TCP 发送可靠数据和通过 UDP 发送所有帧数据变得容易。

于 2013-06-28T13:20:01.700 回答