kibowki
kibowki

Reputation: 4376

How do I set up a Spring TCP client and server model?

So following this question (how to plug a TCP-IP client server in a spring MVC application), I was successfully able to wire a Gateway into my Spring REST controller. However, I'm confused as to where to go next. Here's what I'm trying to accomplish:

1) When a certain route is hit with a POST request, open a connection to a certain IP (or work with a connection that's already open with this IP) passed from the POST and send a message.

@RequestMethod(value = '/sendTcpMessage', method=RequestMethod.POST)
public void sendTcpMessage(@RequestParam(value="ipAddress", required=true) String ipAddress,
                           @RequestParam(value="message", required=true) String message) {

//send the message contained in the 'message' variable to the IP address located 
//at 'ipAddress' - how do I do this?

}

2) I also need my Spring backend to listen to TCP "messages" passed to it, and store them in a buffer. My Javascript will call a route every 5 seconds or so and read the information out of the buffer.

Here is my controller code:

@Controller
public class HomeController {

    @Resource(name = "userDaoImpl")
    private UserDAO userDao;
    @Resource(name = "receiveTcp")
    private ReceiveTcp tcpMessageReceiver;
    @Autowired
    SimpleGateway gw;

    String tcpBuffer[] = new String[100];

    @RequestMapping(value="/")
    public String home() {
        return "homepage";
    }

    @RequestMapping(value = "/checkTcpBuffer", method=RequestMethod.POST)
    public String[] passTcpBuffer() {
        return tcpMessageReceiver.transferBuffer();
    }

}

root-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:int="http://www.springframework.org/schema/integration"
    xmlns:int-ip="http://www.springframework.org/schema/integration/ip"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/integration/ip http://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd
                        http://www.springframework.org/schema/integration/ http://www.springframework.org/schema/integration/spring-integration.xsd">

    <!-- Root Context: defines shared resources visible to all other web components -->
<int:gateway id="gw"
   service-interface="net.codejava.spring.interfaces.SimpleGateway"
   default-request-channel="input"/>

<bean id="javaSerializer"
      class="org.springframework.core.serializer.DefaultSerializer"/>
<bean id="javaDeserializer"
      class="org.springframework.core.serializer.DefaultDeserializer"/>

<int-ip:tcp-connection-factory id="server"
    type="server"
    port="8081"
    deserializer="javaDeserializer"
    serializer="javaSerializer"
    using-nio="true"
    single-use="true"/>

<int-ip:tcp-connection-factory id="client"
    type="client"
    host="localhost"
    port="8081"
    single-use="true"
    so-timeout="10000"
    deserializer="javaDeserializer"
    serializer="javaSerializer"/>

    <int:channel id="input" />

    <int:channel id="replies">
        <int:queue/>
    </int:channel>

    <int-ip:tcp-outbound-channel-adapter id="outboundClient"
    channel="input"
    connection-factory="client"/>

    <int-ip:tcp-inbound-channel-adapter id="inboundClient"
    channel="replies"
    connection-factory="client"/>

    <int-ip:tcp-inbound-channel-adapter id="inboundServer"
    channel="loop"
    connection-factory="server"/>

    <int-ip:tcp-outbound-channel-adapter id="outboundServer"
    channel="loop"
    connection-factory="server"/>

    <int:service-activator input-channel="input" ref="receiveTcp" method = "saveValue"/>

</beans>

ReceiveTcp.java

@Component(value = "receiveTcp")
public class ReceiveTcp {

    String buf[] = new String[100];
    int currentPosition = 0;

    @ServiceActivator
    public void saveValue(String value){
        System.out.println(value);
        buf[currentPosition] = value;
        currentPosition++;
    }

    public String[] transferBuffer() {
        String tempBuf[] = new String[100];
        tempBuf = buf;
        buf = new String[100];

        return tempBuf;
    }
}

How can I resolve these issues?

Upvotes: 2

Views: 10300

Answers (2)

Gary Russell
Gary Russell

Reputation: 174769

See the tcp-client-server sample. It uses TCP gateways (request/reply). For your situation you will likely want to use one-way channel adapters instead.

gateway(with void return) -> tcp-outbound-channel-adapter

and

tcp-inbound-channel-adapter -> service-activator

(where the service activator invokes a POJO that saves the inbound messages in your "buffer", probably keyed by connectionId - obtained from the message header).

Inject the gateway and POJO referenced by the service activator into your controller so you can (a) send messages and (b) empty the "buffer".

You can also listen for TcpConnectionEvents so you can detect if a connection is lost.

Upvotes: 0

Abe
Abe

Reputation: 9061

You need to use a ResponseEntity. See this answer. A tcp connection is a 2-way connection so if your method returns the response instead of void it automatically sends it back to the ip which issued you the request. You don't have to manually do that.

Upvotes: 1

Related Questions