Hasan Can Saral
Hasan Can Saral

Reputation: 3288

Imitate behaviour of OutputStreamWriter with TcpSendingMessageHandler

We used the below piece of code for a Tcp server:

try (ServerSocket serverSocket = new ServerSocket(port)) {
    while (true) {
        Socket socket = serverSocket.accept();
        new ServerThread(socket).start();
    }
}

and ServerThread:

private class ServerThread extends Thread {

        private final Socket socket;

        private ServerThread(Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {

            try (final InputStreamReader reader = new InputStreamReader(socket.getInputStream());
                 final OutputStreamWriter writer = new OutputStreamWriter(socket.getOutputStream())) {

                int bytesRead;
                char[] buffer = new char[1024];

                while ((bytesRead = reader.read(buffer)) != -1){
                    System.out.println(new String(buffer, 0, bytesRead));
                    writer.write(/* some char[] */);
                    writer.flush();
                }

                // ...
                socket.close();

            } catch (IOException exception){
                // ...
                socket.close();
            }
        }
    }

We recently switched to using Spring integration:

        @Bean
        public TcpNetServerConnectionFactory connectionFactory() {
            TcpNetServerConnectionFactory factory = new TcpNetServerConnectionFactory(9000);
            ByteArrayRawSerializer serializer = new ByteArrayRawSerializer();
            factory.setDeserializer(serializer);
            factory.setSerializer(serializer);
            return factory;
        }

        @Bean
        public TcpReceivingChannelAdapter channelAdapter(AbstractServerConnectionFactory connectionFactory) {
            TcpReceivingChannelAdapter adapter = new TcpReceivingChannelAdapter();
            adapter.setConnectionFactory(connectionFactory);
            adapter.setOutputChannel(messageChannel());
            return adapter;
        }

        @Bean
        @ServiceActivator(inputChannel = "outputChannel")
        public TcpSendingMessageHandler messageHandler(AbstractServerConnectionFactory connectionFactory){
            final TcpSendingMessageHandler handler = new TcpSendingMessageHandler();
            handler.setConnectionFactory(connectionFactory());
            return handler;
        }

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

        @Bean
        @Transformer(inputChannel = "messageChannel", outputChannel = "loggingChannel")
        public ObjectToStringTransformer loggingTransformer() {
            return new ObjectToStringTransformer();
        }

        @Bean
        @ServiceActivator(inputChannel = "loggingChannel")
        public void log(String message) {
            System.out.println(message);
        }

with above configuration; we successfully receive messages and print them. When I access the Spring application with a Telnet client, I do get the messages on terminal, however, a client application (written with C++ with WinSock2.h) gets a timeout. What is different with the application and how do I imitate the behaviour of OutputStreamWriters

writer.write(/* some char[] */);
writer.flush();

with TcpSendingMessageHandler for the WinSock2.h application?

Upvotes: 0

Views: 75

Answers (1)

Artem Bilan
Artem Bilan

Reputation: 121177

Did you read ByteArrayRawSerializer JavaDocs? Do you know that it doesn't close a Socket by itself as you do in your custom code after reading and writing?

you probably need to think about closing a Connection after using it.

See this option on the ConnectionFactory:

/**
 * If true, sockets created by this factory will be used once.
 * @param singleUse The singleUse to set.
 */
public void setSingleUse(boolean singleUse) {

Then TcpSendingMessageHandler will close it after sending a message into that OutputStreamWriter.

Upvotes: 0

Related Questions