UDP server with spring integration

I wonder if it is possible to create a UDP server with a spring-integrated structure capable of receiving requests and returning responses.

There are TCP gateways for TCP that allow request / response processing, but I do not see a similar thing for UDP.

It is easy to configure a UDP listener and receive packets, but then I don’t see how to return a response, since I can only redirect it to a predefined output channel.

Also, I do not see the sender's IP address and port, since the transformer does not receive the DatagramPacket, but only the data.

Here is my configuration:

<int:channel id="ChannelIn" /> <ip:udp-inbound-channel-adapter id="ChannelReceiver" channel="ChannelIn" port="5555" multicast="false" check-length="false" pool-size="10" /> <int:transformer ref="datagramToPacketTransformer" input-channel="ChannelIn" output-channel="ChannelSA" method="toPacket"/> <int:channel id="ChannelSA" /> <int:service-activator id="ChannelActivator" input-channel="ChannelSA" ref="PacketHandler" method="process" /> 
+4
source share
3 answers

I found n way to deal with UDP. Below is my configuration

 <int-ip:udp-inbound-channel-adapter id="ChannelReceiver" channel="serverBytes2StringChannel" port="9000" multicast="false" check-length="false" pool-size="10" lookup-host="false" /> <int:transformer id="serverBytes2String" input-channel="serverBytes2StringChannel" output-channel="udpSA" expression="new String(payload)" /> <int:service-activator input-channel="udpSA" ref="deviceService" method="udpMessage"/> 

And deviceService bean has this code:

  public Message udpMessage(Message message) { String response = "KO"; try { response = process(message); } catch (Throwable th) { //do something } Message msg = MessageBuilder.withPayload(response.getBytes()).copyHeaders(message.getHeaders()).build(); sendReply(msg); return null; } private void sendReply(Message message) { try { int port = (Integer) message.getHeaders().get("ip_port"); String ip = (String) message.getHeaders().get("ip_address"); InetAddress IPAddress = InetAddress.getByName(ip); byte[] sentence = (byte[]) message.getPayload(); byte[] sendData = new byte[sentence.length]; byte[] receiveData = new byte[1024]; sendData = sentence; DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port); DatagramSocket clientSocket = new DatagramSocket(); clientSocket.send(sendPacket); clientSocket.close(); } catch (Exception ex) { throw new RuntimeException("KO"); } } 

And this works fine on my personal computer, however, when I deploy this code on Amazon AWS, it doesn't work. I found that even though the program was listening on UDP port 9000, but no communication was received on the server side. This may be an AWS installation issue, although I have allowed the entire UDP port for this AWS instance.

Any tips on how to make this work on Amazon AWS?

+2
source

I discovered the new JIRA function almost two years ago

https://jira.springsource.org/browse/INT-1809

but he did not receive votes or observers, so I closed it.

Feel free to add a comment to it, and we can open it again.

The ip sender is in the message header, but not in its port ...

  message = MessageBuilder.withPayload(payload) .setHeader(IpHeaders.HOSTNAME, hostName) .setHeader(IpHeaders.IP_ADDRESS, hostAddress) .build(); 

If you want to open a new JIRA for this, this is a small enough change to fall into 2.2. a release that will be released shortly (but the gateways will not do 2.2).

https://jira.springsource.org/browse/INT

+1
source

Thanks Gary!

I noticed that the remote IP address is in the headers, but the remote port is wrong, I made some changes to add it.

I extended UnicastReceivingChannelAdapter to override asyncSendMessage where the message is built. I also had to extend the DatagramPacketMessageMapper. It would be easier if I could just introduce my own implementation of the DatagramPacketMessageMapper into the UnicastReceivingChannelAdapter, but that is not possible.

Then in spring configuration I deleted

 <ip:udp-inbound-channel-adapter id="ChannelReceiver"...> 

and the following is added

 <bean id="udpInboundChannelAdapterBean" class="me.spring.integration.udp.UnicastReceivingChannelAdapterExt" init-method="run"> <constructor-arg name="port" value="5555" /> <property name="poolSize" value="10"/> <property name="lookupHost" value="false"/> <property name="outputChannel" ref="ChannelIn" /> 

This seems to work, although I did not have time to fully test it.

My idea is to use the remote IP address and port and the DatagramSocket link from udpInboundChannelAdapterBean to create a new activation service that simply writes the response to the socket.

I will open a new jira for the remote port, as you expected.

-1
source

Source: https://habr.com/ru/post/1436627/


All Articles