将消息发送到套接字端口并使用Spring Integration接收响应

时间:2018-03-01 09:49:34

标签: java spring tcp spring-integration

现状

  • 在linux服务器上,有几个jar正在运行套接字 - 用字符串消息监听和响应
  • 在wildfly应用程序服务器中运行的新war正在将请求委托给这些套接字
  • WAR使用弹簧,特别是弹簧与注释集成

我有一个包含服务的配置类@Configuration / @EnableIntegration / @ IntegrationComponentScan

我已经创建了一个消息传递网关

@MessagingGateway(defaultRequestChannel = "testGateway")
public interface TestGateway{
    public Future<String> sendMessage(String in);
}

应用程序应发送请求并以客户端身份接收请求。我创建了一个null事件处理程序,因为应用程序应该只发送字符串并等待答案

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

@Bean
@ServiceActivator(inputChannel = "testGateway")
public MessageHandler testGate() {
    final TcpOutboundGateway gate = new TcpOutboundGateway();
    gate.setConnectionFactory(connectionFactory());
    gate.setReplyChannel(docServerChannel());
    return gate;
}

@Bean
public AbstractClientConnectionFactory connectionFactory() {
    final AbstractClientConnectionFactory connectionFactory = new TcpNetClientConnectionFactory("localhost", 5959);
    connectionFactory.setSoTimeout(300000);
    connectionFactory.setApplicationEventPublisher(new NullEventPublisher());
    connectionFactory.setSerializer(new DefaultSerializer());
    connectionFactory.setDeserializer(new DefaultDeserializer());
    return connectionFactory;
}

接收数据时应将消息转换为字符串,发送时应将字节转换为字节

@MessageEndpoint
public static class TestMessage {

    @Transformer(inputChannel = "testChannel")
    public String convert(final byte[] bytes) {
        return new String(bytes);
    }

    @Transformer(inputChannel = "testGateway")
    public String convertResult(final byte[] bytes) {
        return new String(bytes);
    }

}

部署了应用程序,但响应始终超时。套接字正在运行。我只想要一个简单的直接双向连接:WAR&lt; - &gt; JAR。

有人可以帮忙或给我一个暗示吗?

------ UPDATE-1 ----------

套接字正在接收消息,但是在发送消息后套接字关闭时无法读取响应。

------ UPDATE-2 ----------

  • 这是一个错字。系统返回MessageHandler
  • 我已将工厂添加为spring managed bean
  • 我已将'\ r \ n'添加到旧代码
  • 该应用程序仍在抱怨“等待响应超时”

旧版服务器正在打开服务器套接字并向套接字

发送消息
final OutputStream os = serverSocket.getOutputStream();
final PrintWriter pw = new PrintWriter(os, true);
final BufferedReader br = new BufferedReader(new InputStreamReader(serverSocket.getInputStream()));
final String incoming = br.readLine();
final String response= "ok\r\n";
pw.println(response);
pw.flush();
Thread.sleep(5000);
pw.close();
serverSocket.close();

------ UPDATE-3 ----------

来自Spring的TcpOutboundGateway没有得到回应

        connection.send(requestMessage);
        Message<?> replyMessage = reply.getReply();
        if (replyMessage == null) {

1 个答案:

答案 0 :(得分:1)

连接工厂需要是@Bean,以便Spring可以管理它。

public TcpInboundGateway testGate() {
    final AbstractClientConnectionFactory connectionFactory = new TcpNetClientConnectionFactory("localhost", 5959); // already running socket
    connectionFactory.setApplicationEventPublisher(new NullEventPublisher());
    final TcpOutboundGateway gate = new TcpOutboundGateway();
    gate.setConnectionFactory(connectionFactory);
    gate.setOutputChannelName("testChannel");
    return gate;
}

这不会编译;返回类型与您返回的内容不匹配。

假设这只是一个拼写错误而且bean实际上是一个出站网关,使用此配置,回复必须以\r\n(CRLF)终止。

the documentation;向下滚动到...

  

TCP是一种流媒体协议;这意味着必须为通过TCP传输的数据提供一些结构,因此接收器可以将数据划分为离散消息。连接工厂配置为使用(反)序列化器在消息有效负载和通过TCP发送的位之间进行转换。这是通过分别为入站和出站消息提供解串器和串行器来实现的。提供了许多标准(de)序列化器。

...并阅读标准反序列化器。使用您的配置,标准反序列化程序正在等待终止\r\n(CRLF)。

服务器代码有什么作用?

修改

@SpringBootApplication
public class So49046888Application {

    public static void main(String[] args) throws Exception {
        ConfigurableApplicationContext ctx = SpringApplication.run(So49046888Application.class, args);
        String reply = ctx.getBean(TestGateway.class).sendMessage("foo").get();
        System.out.println(reply);
        Thread.sleep(10_000);
        ctx.close();
    }

    @Bean
    public ServerSocket serverSocket() throws IOException {
        return ServerSocketFactory.getDefault().createServerSocket(5959);
    }

    @Bean
    public ApplicationRunner runner(TaskExecutor exec) {
        return args -> {
            exec.execute(() -> {
                try {
                    while (true) {
                        Socket socket = serverSocket().accept();
                        final OutputStream os = socket.getOutputStream();
                        final PrintWriter pw = new PrintWriter(os, true);
                        final BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                        final String incoming = br.readLine();
                        System.out.println(incoming);
                        final String response= "ok\r\n";
                        pw.print(response);
                        pw.flush();
                        Thread.sleep(5000);
                        pw.close();
                        socket.close();
                    }
                }
                catch (Exception e) {
                    e.printStackTrace();
                }
            });
        };
    }

    @Bean
    public TaskExecutor exec() {
        return new ThreadPoolTaskExecutor();
    }

    @Bean
    @ServiceActivator(inputChannel = "testGateway")
    public MessageHandler testGate() {
        final TcpOutboundGateway gate = new TcpOutboundGateway();
        gate.setConnectionFactory(connectionFactory());
        gate.setReplyChannelName("toString");
        gate.setRemoteTimeout(60_000);
        return gate;
    }

    @Transformer(inputChannel = "toString")
    public String transform(byte[] bytes) {
        return new String(bytes);
    }

    @Bean
    public AbstractClientConnectionFactory connectionFactory() {
        final AbstractClientConnectionFactory connectionFactory = new TcpNetClientConnectionFactory("localhost", 5959);
        connectionFactory.setSoTimeout(300000);
        return connectionFactory;
    }

    @MessagingGateway(defaultRequestChannel = "testGateway")
    public static interface TestGateway {
        public Future<String> sendMessage(String in);
    }

}