java Netty - UDP 服务器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17321850/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-01 01:41:10  来源:igfitidea点击:

Netty - UDP server

javaudpnetty

提问by thelost

I am having an UDP Netty based server. It has a SimpleChannelUpstreamHandlerpipelined where I override the messageReceivedmethod.

我有一个基于 UDP Netty 的服务器。它有一个SimpleChannelUpstreamHandler管道,我可以在其中覆盖该messageReceived方法。

I need to write back some information now and then. I could only do that by using the socket information from MessageEvent.getRemoteAddress(), and the channel from MessageEvent.getChannel(). In order to be able to reuse this information I keep in in a static map.

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

This turns into MessageEvent.getChannel().write("foo", MessageEvent.getRemoteAddress());

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

What I would have expected was to have MessageEvent.getChannel().getRemoteAddress()work, which is not the case. It always gives me null.

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

  1. Am I doing something wrong ?
  2. Is there a better way for writing back than keeping the channel and remote address in some member ?
  1. 难道我做错了什么 ?
  2. 有没有比在某个成员中保留频道和远程地址更好的回写方法?

回答by Yoav Slomka

when using a UDP (Datagram) channel as a server channel, you only bind it on a local address and no connection is made. this is why there is no remote address associated with the channel and you always get nullwhen calling MessageEvent.getChannel().getRemoteAddress(). this behavior is expected and correct. the same single UDP "server" channel handles all incoming client requests.

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

when using a UDP channel as a client channel, one can create a "connection" by connecting the channel to a remote address. in this case the channel will have a configured remote address (although no actual connection is made) and calling MessageEvent.getChannel().getRemoteAddress()will return the configured remote address. connecting a UDP channel prevents the user from using the channel to send data to remotes addresses other then the one configured on the channel. trying to do so will throw an exception. connecting a client channel is optional in UDP, a client can operate properly with a channel which is only binded on a local address as long as it saves the remote address.

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

I think you have two options:

我认为你有两个选择:

  1. saving the clients remote addresses with the client identifier and using the "server" channel to sent the data. saving the channel won't work because the same channel will used for communicating with all clients.
  2. creating a new connected channel for each client, and saving the new channels with the client identifiers.
  1. 使用客户端标识符保存客户端远程地址并使用“服务器”通道发送数据。保存频道将不起作用,因为同一个频道将用于与所有客户端进行通信。
  2. 为每个客户端创建一个新的连接通道,并使用客户端标识符保存新通道。

I believe the first option is better.

我相信第一种选择更好。

回答by johnstlr

As you're probably aware UDP is a connection-less transport. A single channel can receive data from, and write data to any destination address. Therefore a UDP channel does not have an associated remote address in the way that a TCP channel does. While I think it's possible to get netty to associate a UDP channel with a specific remote address, I haven't got the details to hand and, to be honest, I think getting the address from the message event is the better option.

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

This leads into your second question in that, yes, you will need to keep the remote address somewhere. I've not done any UDP programming in Netty so I'm not sure if you need to map the remote address to a channel object, or whether Netty is always returning the same channel object regardless. It's worth checking this as you may only need to keep a single reference to the channel.

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

回答by Abe

1) Take a look at this UDP upstream handler. To get the remote address of the sender you can use the following code SocketAddress remoteAddress = datagramPacket.sender();
2) What @johnstlr mentioned is right, it is not correct to associate a UDP channel with a single remote address. But you can use a concurrent hashmap to do lookups as shown in the above file. This game serveractually uses sessions which have both TCP and UDP connections. This makes it easy to send reliable data over TCP and all the frame data over UDP.

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