Search code examples
spring-bootkotlinspring-integrationspring-integration-dsl

Spring TCP Integration only reads every 30+ seconds


I'm having an issue making a TCP Server using Spring-Integration. I've set my server up to accept TCP Connections from a black box client. The client will connect to the server and start periodically sending it string data.

What I'm seeing is after the connection is established (I get confirmation from the client side) I don't receive a print statement on the server until about 30 seconds have passed, where I get 5 messages all at once.

I've monitored incoming data over wireshark and the client is sending data at regular intervals, but the server doesn't read from the incomingStream frequently enough. Is there a way to configure the TcpServer that it reads data from incoming clients more frequently?

fun flow() = IntegrationFlows.from(
            Tcp.inboundAdapter(Tcp.nioServer(port).serializer(ByteArrayRawSerializer()).deserializer(ByteArrayRawSerializer()))
                .errorChannel(errorChannel())
            )
            .transform(ObjectToStringTransformer())
            .handle { payload: String, headers: MessageHeaders ->
                println(payload)
            }
            .get()

Solution

  • The ByteArrayRawSerializer uses the socket close to detect the end of a message.

    TCP is a streaming protocol and, if you want to send multiple messages over the socket, you need to delimit the data somehow so the server can determine when one message ends and the next one starts. See the documentation.

    TCP is a streaming protocol. This means that some structure has to be provided to data transported over TCP so that the receiver can demarcate the data into discrete messages. Connection factories are configured to use serializers and deserializers to convert between the message payload and the bits that are sent over TCP. This is accomplished by providing a deserializer and a serializer for inbound and outbound messages, respectively. Spring Integration provides a number of standard serializers and deserializers.

    ...

    The ByteArrayRawSerializer, converts a byte array to a stream of bytes and adds no additional message demarcation data. With this serializer (and deserializer), the end of a message is indicated by the client closing the socket in an orderly fashion. When using this serializer, message reception hangs until the client closes the socket or a timeout occurs.

    My guess is the client is not closing the connection after sending the message and there is a 30 second SO timeout (either on the client or server - you don't show your connection factory configuration).