5
votes

I am having an UDP Netty based server. It has a SimpleChannelUpstreamHandler pipelined where I override the messageReceived method.

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.

This turns into 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.

  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 ?
3

3 Answers

5
votes

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 null when calling MessageEvent.getChannel().getRemoteAddress(). this behavior is expected and correct. the same single UDP "server" channel handles all incoming client requests.

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.

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.

I believe the first option is better.

2
votes

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.

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.

2
votes

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 server actually 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.