【问题标题】:Spring integration tcp-connection-factory closes client connection before replySpring集成tcp-connection-factory在回复前关闭客户端连接
【发布时间】:2015-03-14 02:35:40
【问题描述】:

我对弹簧集成有一些问题。 可以说,有我的传出通信配置:

<int:channel id="outputChannel">
    <int:queue /> 
</int:channel>

<int:channel id="outputChannel-in"> <!-- for response from server -->
    <int:queue /> 
</int:channel>

<int-ip:tcp-connection-factory 
    id="outputSocket"
    type="client" 
    single-use="true"
    host="localhost"
    port="666" />

<int-ip:tcp-outbound-gateway id="outGateway"
    request-channel="outputChannel"
    reply-channel="outputChannel-in"
    connection-factory="outputSocket"
    reply-timeout="20000" />

<int:gateway id="myGateway"
     service-interface="some.package.SocketGateway"
     default-request-channel="outputChannel"
     default-reply-channel="outputChannel-in" />

<int:service-activator
    id="myServiceActivator" 
    input-channel="outputChannel-in" 
    ref="myService"
    method="incomingDataHandlingMethod" />

不管我对接口 some.package.SocketGateway 做什么:

选项#1:

public interface SocketGateway{
    byte[] send(String text);
}

选项#2:

public interface SocketGateway{
    Future<byte[]> send(String text);
}

它没有收到任何消息。 我玩了很多配置。这只是我的解决方案的一个版本,但它们都不起作用。

这是一个服务器模拟:

ServerSocket someSocket = new ServerSocket(666);
Socket socket = someSocket.accept();

PrintWriter  out =
    new PrintWriter (socket.getOutputStream(), true);
BufferedReader in =
    new BufferedReader(
        new InputStreamReader(socket.getInputStream()));

System.out.println("socket accepted");

String data = in.readLine();
while (data != null) {
    System.out.println(data);
    data = in.readLine();
} 

System.out.println("data received");
out.println("ACK");

out.flush();  
System.out.println("data sent");
socket.close();
someSocket.close();

out.println("ACK"); 在while 之后时,连接关闭并且不发送ACK。当out.println("ACK"); 在while 或 inside 之前时,它会发送消息。

我应该怎么做才能收到这条消息?

编辑: 我也试过:

<int-ip:tcp-outbound-channel-adapter
    id="outboundClient"
    channel="outputChannel"
    connection-factory="outputSocket" />

<int-ip:tcp-inbound-channel-adapter
    id="outboundClient-in"
    channel="outputChannel-in"
    connection-factory="outputSocket" />

没有好的结果。

编辑: 我有这个客户端代码:

Socket echoSocket = new Socket("10.20.30.40", 11111);
PrintWriter out = new PrintWriter(echoSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));

String encodedMessage = "someMessage";

String result = String.format("%c%s%c%c", (char) 11, encodedMessage, (char) 28, (char) 13);

            out.println(result);
out.flush();
System.out.println("data sent");

File file = new File("result.txt");
BufferedWriter output = new BufferedWriter(new FileWriter(file));

String data;
while ((data = in.readLine()) != null) {
    output.write(data);
}

output.flush();
output.close();

System.out.println("after while");
out.close();
in.close();
echoSocket.close();

这在外部服务器上工作得很好(服务器正在同步发送 ACK 消息,该消息在 String data 中接收。如何通过 Spring Integration 实现这个结果?我什么都收不到...

【问题讨论】:

    标签: java spring sockets tcp spring-integration


    【解决方案1】:

    TCP 是一个流;它需要结构来分隔消息。默认的反序列化程序在末尾需要 CRLF。

    发送out.println("ACK\r\n");

    您可以阅读Serializers 和Deserializers here

    编辑:

    你的逻辑在几个方面存在缺陷。

    1. 使用PrintWriter.println() 只附加LF;除非您更改反序列化器,否则您需要 CRLF。
    2. 您的“服务器”挂在readLine() 上,直到套接字关闭。

    这很好用:

    ServerSocket someSocket = new ServerSocket(1666);
    Socket socket = someSocket.accept();
    
    OutputStream out = socket.getOutputStream();
    BufferedReader in =
        new BufferedReader(
            new InputStreamReader(socket.getInputStream()));
    
    System.out.println(Thread.currentThread().getName() +  " socket accepted");
    
    String data = in.readLine();
    System.out.println(data);
    
    System.out.println("data received");
    out.write("ACK\r\n".getBytes());
    
    out.flush();
    System.out.println("data sent");
    socket.close();
    someSocket.close();
    

    【讨论】:

    • 它不起作用。如果我在一段时间内或之前发送一些消息,它将被客户端套接字接收。当我在接口上调用 send 时,它会发送消息,等待 20 秒等待回复,然后引发org.springframework.integration.MessageTimeoutException: Timed out waiting for response。如果 send 在 while 中,则进入回复通道,然后调用 service-activator 方法。
    • 确实如此。感谢您的回复。现在它起作用了。这只是一些Mock,另一边是另一台服务器,但现在我知道我的配置很好,他们必须解决这个问题,而不是我:)
    • 您好,我在从外部服务器接收数据时仍有问题。简单的java客户端工作正常,但是spring集成收不到数据
    • 更多信息在第二个编辑主要问题 - 提前致谢!
    • 如我之前所说,如果服务器仅使用LF 分隔数据,而不是CRLF(这是默认反序列化器所期望的),则需要更改序列化器/反序列化器到ByteArrayLfSerializer。请阅读我推荐给您的文档。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-26
    • 1970-01-01
    • 2016-09-15
    • 1970-01-01
    • 1970-01-01
    • 2018-12-14
    • 1970-01-01
    相关资源
    最近更新 更多