bacalum
bacalum

Reputation: 1

Spring Integration : Failed to send reply after netcat's command

My use case :

  1. Client netcat to send tcp socket to the server
echo -n "coincoincoin" | nc -v host port
  1. Server tcp with Spring Integration receive the request from client
  2. Sever receiving the request with TcpInboundGateway, process
  3. Server send back the reply to the client through TcpInboundGateway
  4. The client receives and display the answer.

Unfortunately, the step from one to 3 is OK. The step 4 is not OK and I get a

... Failed to send reply ...

The server config's file :

@Configuration
public class ServerConfig {

    @Value("${server.port}")
    private int port;

   @Bean
    TcpNetServerConnectionFactory serverConnexion() {
        TcpNetServerConnectionFactory factory = new TcpNetServerConnectionFactory(port);
        factory.setSingleUse(true);
        factory.setDeserializer(new CustomSerializerDeserializer());
        factory.setSerializer(new CustomSerializerDeserializer());
       factory.setSoTimeout(10000);
        return factory;
    }

    @Bean
    TcpInboundGateway tcpGateway() {
        TcpInboundGateway gateway = new TcpInboundGateway();
        gateway.setConnectionFactory(serverConnexion());
        gateway.setRequestChannel(reqChannel());
        gateway.setReplyChannel(reqChannel());
        return gateway;
    }

    @Bean
    public MessageChannel reqChannel() {
        return new DirectChannel();
    }
}

Here is my exception :

2022-12-18 14:21:51.524 DEBUG 14816 --- [pool-3-thread-2] org.springframework.integration.channel.DirectChannel : [( - )] postSend (sent=true) on channel 'bean 'reqChannel'; defined in: 'class path resource [com/server/config/ServerConfig.class]'; from source: 'com.rss.server.config.ServerConfig.reqChannel()'', message: GenericMessage [payload=byte[40], headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@68980b5b, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@68980b5b, ip_tcp_remotePort=38567, ip_connectionId=kubernetes.docker.internal:38567:11000:e143aeae-532c-4aab-9ef1-ba7930ecc3ef, ip_localInetAddress=0.0.0.0/0.0.0.0, ip_address=127.0.0.1, id=3265835d-8088-7820-d7e5-0dd46ddab69c, ip_hostname=kubernetes.docker.internal, timestamp=1671369710212}]
2022-12-18 14:21:51.524 ERROR 14816 --- [pool-3-thread-2] org.springframework.integration.ip.tcp.TcpInboundGateway : [( - )] Failed to send reply
org.springframework.messaging.MessagingException: Send Failed; nested exception is java.net.SocketException: Socket is closed
    at org.springframework.integration.ip.tcp.connection.TcpNetConnection.send(TcpNetConnection.java:119) ~[spring-integration-ip-5.5.8.jar:5.5.8]
    at org.springframework.integration.ip.tcp.TcpInboundGateway.doOnMessage(TcpInboundGateway.java:139) [spring-integration-ip-5.5.8.jar:5.5.8]
    at org.springframework.integration.ip.tcp.TcpInboundGateway.onMessage(TcpInboundGateway.java:101) [spring-integration-ip-5.5.8.jar:5.5.8]
    at org.springframework.integration.ip.tcp.connection.TcpNetConnection.receiveAndProcessMessage(TcpNetConnection.java:224) [spring-integration-ip-5.5.8.jar:5.5.8]
    at org.springframework.integration.ip.tcp.connection.TcpNetConnection.run(TcpNetConnection.java:197) [spring-integration-ip-5.5.8.jar:5.5.8]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [?:?]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [?:?]
    at java.lang.Thread.run(Thread.java:834) [?:?]
Caused by: java.net.SocketException: Socket is closed
    at java.net.Socket.getSendBufferSize(Socket.java:1215) ~[?:?]
    at org.springframework.integration.ip.tcp.connection.TcpNetConnection.send(TcpNetConnection.java:108) ~[spring-integration-ip-5.5.8.jar:5.5.8]
    ... 7 more

How can I solve this problem ? Any help would be welcome! Thank you very much!

Upvotes: 0

Views: 245

Answers (1)

Gary Russell
Gary Russell

Reputation: 174554

It looks like piping the echo into nc closes the socket before the response is sent; this works fine for me...

@Component
class ServerConfig {

    private final int port = 1234;

    @Bean
    TcpNetServerConnectionFactory serverConnexion() {
        TcpNetServerConnectionFactory factory = new TcpNetServerConnectionFactory(port);
        factory.setSingleUse(true);
//      factory.setDeserializer(new CustomSerializerDeserializer());
//      factory.setSerializer(new CustomSerializerDeserializer());
        factory.setSoTimeout(10000);
        return factory;
    }

    @Bean
    TcpInboundGateway tcpGateway(TcpNetServerConnectionFactory serverConnexion, MessageChannel reqChannel) {
        TcpInboundGateway gateway = new TcpInboundGateway();
        gateway.setConnectionFactory(serverConnexion);
        gateway.setRequestChannel(reqChannel);
        gateway.setReplyChannel(reqChannel);
        return gateway;
    }

    @Bean
    public MessageChannel reqChannel() {
        return new DirectChannel();
    }

}

Note that I am using the default (de)serializer (CRLF).

% nc -cv localhost 1234
Connection to localhost port 1234 [tcp/search-agent] succeeded!
foo
foo

Upvotes: 1

Related Questions