kevin
kevin

Reputation: 570

How to use so-linger to keep server connection for some time

I have TCP gateway built using Spring Integration. My server is able to process the request from the client and send response. But Client is giving SocketException

java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(SocketInputStream.java:168)
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
    at sun.nio.cs.StreamDecoder.read0(StreamDecoder.java:107)
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:93)
    at java.io.InputStreamReader.read(InputStreamReader.java:151)

It seems server is closing the connection before the client reads all the data. Hence I would like to use so-linger.

setSoLinger is supposed to keep the server socket open for the linger time. javadoc for setSoLinger says Enable/disable SO_LINGER with the specified linger time in seconds.

See https://docs.oracle.com/javase/6/docs/api/java/net/Socket.html#setSoLinger%28boolean,%20int%29

See Spring Integration document for setting SoLinger.

My spring context.xml :

    <int-ip:tcp-connection-factory id="crLfServer"
            type="server"
            port="${availableServerSocket}"
            single-use="true"
            so-timeout="10000"
            using-nio="false" 
            serializer="connectionSerializeDeserialize"
            deserializer="connectionSerializeDeserialize"
            so-linger="2000"/>

        <bean id="connectionSerializeDeserialize" class="org.springframework.integration.ip.tcp.serializer.ByteArrayStxEtxSerializer"/>

        <int-ip:tcp-inbound-gateway id="gatewayCrLf"
            connection-factory="crLfServer"
            request-channel="serverBytes2StringChannel"
            error-channel="errorChannel"
            reply-timeout="10000"/> <!-- reply-timeout works on inbound-gateway -->

        <int:channel id="toSA" />

        <int:service-activator input-channel="toSA"
            ref="myService"
            method="prepare"/>

        <int:object-to-string-transformer id="serverBytes2String"
            input-channel="serverBytes2StringChannel"
            output-channel="toSA"/>

        <int:transformer id="errorHandler"
            input-channel="errorChannel"
            expression="payload.failedMessage.payload + ':' + payload.cause.message"/>

I am not sure whether Spring integration takes linger time in seconds or milli seconds. is there any other flag to be set so that Server socket is kept open till the client reads data.

I am seeing Socket connection closed event almost immediately sending response from the service bean. Server does not seem to wait. Please help how to set so-linger time or suggest alternative. Thank you.

Here is the log:

2016-06-01 15:43:46,276 MyService response:                 ACCEPT:E211001:

2016-06-01 15:43:46.293 DEBUG [pool-1-thread-2][org.springframework.context.support.GenericXmlApplicationContext] Publishing event in org.springframework.context.support.GenericXmlApplicationContext@7a187814: TcpConnectionCloseEvent [source=org.springframework.integration.ip.tcp.connection.TcpNetConnection@4c4b11e9], [factory=crLfServer, connectionId=22.220.220.222:1034:5678:77483643-2156-427f-96dd-a513670a75a3] **CLOSED**

2016-06-01 15:43:46.294 DEBUG [pool-1-thread-2][org.springframework.context.support.GenericXmlApplicationContext] Publishing event in org.springframework.context.support.GenericXmlApplicationContext@7a187814: TcpConnectionExceptionEvent [source=org.springframework.integration.ip.tcp.connection.TcpNetConnection@4c4b11e9, cause=java.net.SocketException: Socket is closed], [factory=crLfServer, connectionId=22.220.220.222:1034:5678:77483643-2156-427f-96dd-a513670a75a3]

Upvotes: 2

Views: 2481

Answers (1)

Gary Russell
Gary Russell

Reputation: 174554

Spring integration performs no conversion on the value, so it's seconds.

The behavior you describe sounds like so-linger is 0 (immediate RST sent for close()).

You really don't need so linger for this purpose; when it's not set the TCP stack should gracefully close the socket.

You probably need to run a network monitor to figure out what's happening.

If you trust your client to close the socket, you could remove the

single-use="true"

or set it to false so the server doesn't close the socket after sending the reply.

Upvotes: 1

Related Questions