我想使用spring集成与另一台服务器进行TCP通信(用C语言编写)。
服务器之间的Exchange数据是原始字节,但消息没有分隔符。
因此,我编写了自己的Serializer / Deserializer,扩展了 AbstractByteArraySerializer 。
但是,当我通过MessagingGateway发送消息时 - > TcpOutboundGateway - > TcpNioClientConnectionFactory,回复消息挂起,直到超时TcpNioConnection发生。
这是我的SI java配置:
@Bean(name = "loggingChannel")
public MessageChannel loggingChannel() {
return new DirectChannel();
}
@Bean
@GlobalChannelInterceptor()
public ChannelInterceptor wiretap() {
return new WireTap(loggingChannel(), s -> true);
}
private int port = 10101;
private String host = "10.1.3.119";
@Bean
public MessageChannel toTcp() {
return new DirectChannel();
}
@Bean
public MessageChannel fromTcp() {
return new DirectChannel();
}
@Autowired
public PerunGateway perunGateway;
@MessagingGateway(defaultRequestChannel = "toTcp", defaultReplyChannel = "fromTcp")
public interface PerunGateway {
@Gateway
byte[] sendCommand(byte[] message);
}
@Bean
@ServiceActivator(inputChannel = "toTcp")
public TcpOutboundGateway tcpOutGate() {
TcpOutboundGateway gate = new TcpOutboundGateway();
gate.setConnectionFactory(clientConnectionFactory());
gate.setOutputChannelName("fromTcp");
gate.setRequestTimeout(5000);
return gate;
}
@Bean
public AbstractClientConnectionFactory clientConnectionFactory() {
TcpNioClientConnectionFactory tnccf = new TcpNioClientConnectionFactory(host, port);
tnccf.setSoTimeout(1000);
tnccf.setSingleUse(true);
tnccf.setSerializer(new SunByteArrayRawSerializer());
tnccf.setDeserializer(new SunByteArrayRawSerializer());
return tnccf;
}
发送消息后我得到输出:
2015-11-12 13:49:09.032 DEBUG 10329 --- [nio-8080-exec-1] o.s.integration.channel.DirectChannel : preSend on channel 'toTcp', message: GenericMessage [payload=byte[150], headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@66e6fc48, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@66e6fc48, id=e5425395-e1cb-8cc7-20fd-eb5b9be3a615, timestamp=1447332549031}]
2015-11-12 13:49:09.032 DEBUG 10329 --- [nio-8080-exec-1] o.s.integration.channel.DirectChannel : preSend on channel 'loggingChannel', message: GenericMessage [payload=byte[150], headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@66e6fc48, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@66e6fc48, id=e5425395-e1cb-8cc7-20fd-eb5b9be3a615, timestamp=1447332549031}]
2015-11-12 13:49:09.033 DEBUG 10329 --- [nio-8080-exec-1] o.s.integration.handler.LoggingHandler : org.springframework.integration.handler.LoggingHandler#0 received message: GenericMessage [payload=byte[150], headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@66e6fc48, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@66e6fc48, id=e5425395-e1cb-8cc7-20fd-eb5b9be3a615, timestamp=1447332549031}]
2015-11-12 13:49:09.033 INFO 10329 --- [nio-8080-exec-1] o.s.integration.handler.LoggingHandler : GenericMessage [payload=byte[150], headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@66e6fc48, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@66e6fc48, id=e5425395-e1cb-8cc7-20fd-eb5b9be3a615, timestamp=1447332549031}]
2015-11-12 13:49:09.034 DEBUG 10329 --- [nio-8080-exec-1] o.s.integration.channel.DirectChannel : postSend (sent=true) on channel 'loggingChannel', message: GenericMessage [payload=byte[150], headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@66e6fc48, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@66e6fc48, id=e5425395-e1cb-8cc7-20fd-eb5b9be3a615, timestamp=1447332549031}]
2015-11-12 13:49:09.034 DEBUG 10329 --- [nio-8080-exec-1] o.s.i.ip.tcp.TcpOutboundGateway : tcpOutGate received message: GenericMessage [payload=byte[150], headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@66e6fc48, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@66e6fc48, id=e5425395-e1cb-8cc7-20fd-eb5b9be3a615, timestamp=1447332549031}]
2015-11-12 13:49:09.034 DEBUG 10329 --- [nio-8080-exec-1] .s.i.i.t.c.TcpNioClientConnectionFactory : Opening new socket connection to 10.1.3.119:10101
2015-11-12 13:49:09.042 DEBUG 10329 --- [nio-8080-exec-1] o.s.i.i.tcp.connection.TcpNioConnection : New connection 10.1.3.119:10101:38308:430e8a01-3d8a-462a-85a7-00ff6ce70b19
2015-11-12 13:49:09.043 DEBUG 10329 --- [nio-8080-exec-1] .s.i.i.t.c.TcpNioClientConnectionFactory : clientConnectionFactory: Added new connection: 10.1.3.119:10101:38308:430e8a01-3d8a-462a-85a7-00ff6ce70b19
2015-11-12 13:49:09.045 TRACE 10329 --- [pool-1-thread-1] .s.i.i.t.c.TcpNioClientConnectionFactory : clientConnectionFactory: Connection is open: 10.1.3.119:10101:38308:430e8a01-3d8a-462a-85a7-00ff6ce70b19
2015-11-12 13:49:09.045 TRACE 10329 --- [pool-1-thread-1] .s.i.i.t.c.TcpNioClientConnectionFactory : Host 10.1.3.119 port 10101 SelectionCount: 0
2015-11-12 13:49:09.048 DEBUG 10329 --- [nio-8080-exec-1] o.s.i.ip.tcp.TcpOutboundGateway : Added pending reply 10.1.3.119:10101:38308:430e8a01-3d8a-462a-85a7-00ff6ce70b19
2015-11-12 13:49:09.049 DEBUG 10329 --- [nio-8080-exec-1] o.s.i.i.tcp.connection.TcpNioConnection : 10.1.3.119:10101:38308:430e8a01-3d8a-462a-85a7-00ff6ce70b19 writing 150
2015-11-12 13:49:09.049 DEBUG 10329 --- [nio-8080-exec-1] o.s.i.i.tcp.connection.TcpNioConnection : 10.1.3.119:10101:38308:430e8a01-3d8a-462a-85a7-00ff6ce70b19 Message sent GenericMessage [payload=byte[150], headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@66e6fc48, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@66e6fc48, id=e5425395-e1cb-8cc7-20fd-eb5b9be3a615, timestamp=1447332549031}]
2015-11-12 13:49:09.111 TRACE 10329 --- [pool-1-thread-1] .s.i.i.t.c.TcpNioClientConnectionFactory : clientConnectionFactory: Connection is open: 10.1.3.119:10101:38308:430e8a01-3d8a-462a-85a7-00ff6ce70b19
2015-11-12 13:49:09.111 TRACE 10329 --- [pool-1-thread-1] .s.i.i.t.c.TcpNioClientConnectionFactory : Host 10.1.3.119 port 10101 SelectionCount: 1
2015-11-12 13:49:09.114 DEBUG 10329 --- [pool-1-thread-2] o.s.i.i.tcp.connection.TcpNioConnection : 10.1.3.119:10101:38308:430e8a01-3d8a-462a-85a7-00ff6ce70b19 Reading...
2015-11-12 13:49:09.115 DEBUG 10329 --- [pool-1-thread-2] o.s.i.i.tcp.connection.TcpNioConnection : 10.1.3.119:10101:38308:430e8a01-3d8a-462a-85a7-00ff6ce70b19 Running an assembler
2015-11-12 13:49:09.115 TRACE 10329 --- [pool-1-thread-2] o.s.i.i.tcp.connection.TcpNioConnection : Before read:0/61440
2015-11-12 13:49:09.115 TRACE 10329 --- [pool-1-thread-3] o.s.i.i.tcp.connection.TcpNioConnection : 10.1.3.119:10101:38308:430e8a01-3d8a-462a-85a7-00ff6ce70b19 Nio message assembler running...
2015-11-12 13:49:09.115 TRACE 10329 --- [pool-1-thread-3] o.s.i.i.tcp.connection.TcpNioConnection : 10.1.3.119:10101:38308:430e8a01-3d8a-462a-85a7-00ff6ce70b19 checking data avail: 0 pending: true
2015-11-12 13:49:09.116 TRACE 10329 --- [pool-1-thread-3] o.s.i.i.tcp.connection.TcpNioConnection : 10.1.3.119:10101:38308:430e8a01-3d8a-462a-85a7-00ff6ce70b19 checking data avail (convert): 0 pending: true
2015-11-12 13:49:09.116 TRACE 10329 --- [pool-1-thread-2] o.s.i.i.tcp.connection.TcpNioConnection : After read:102/61440
2015-11-12 13:49:09.116 TRACE 10329 --- [pool-1-thread-2] o.s.i.i.tcp.connection.TcpNioConnection : After flip:0/102
2015-11-12 13:49:09.116 DEBUG 10329 --- [pool-1-thread-2] o.s.i.i.tcp.connection.TcpNioConnection : Read 102 into raw buffer
2015-11-12 13:49:09.116 TRACE 10329 --- [pool-1-thread-2] o.s.i.i.tcp.connection.TcpNioConnection : 10.1.3.119:10101:38308:430e8a01-3d8a-462a-85a7-00ff6ce70b19 Sending 102 to pipe
2015-11-12 13:49:09.116 TRACE 10329 --- [pool-1-thread-1] .s.i.i.t.c.TcpNioClientConnectionFactory : clientConnectionFactory: Connection is open: 10.1.3.119:10101:38308:430e8a01-3d8a-462a-85a7-00ff6ce70b19
2015-11-12 13:49:09.117 TRACE 10329 --- [pool-1-thread-1] .s.i.i.t.c.TcpNioClientConnectionFactory : Host 10.1.3.119 port 10101 SelectionCount: 0
2015-11-12 13:49:10.117 WARN 10329 --- [pool-1-thread-1] .s.i.i.t.c.TcpNioClientConnectionFactory : Timing out TcpNioConnection 10.1.3.119:10101:38308:430e8a01-3d8a-462a-85a7-00ff6ce70b19
2015-11-12 13:49:10.118 DEBUG 10329 --- [pool-1-thread-1] .s.i.i.t.c.TcpNioClientConnectionFactory : clientConnectionFactory: Removed closed connection: 10.1.3.119:10101:38308:430e8a01-3d8a-462a-85a7-00ff6ce70b19
2015-11-12 13:49:10.119 TRACE 10329 --- [pool-1-thread-1] .s.i.i.t.c.TcpNioClientConnectionFactory : Host 10.1.3.119 port 10101 SelectionCount: 0
2015-11-12 13:49:11.117 TRACE 10329 --- [pool-1-thread-3] o.s.i.i.tcp.connection.TcpNioConnection : 10.1.3.119:10101:38308:430e8a01-3d8a-462a-85a7-00ff6ce70b19 checking data avail: 0 pending: false
2015-11-12 13:49:11.117 TRACE 10329 --- [pool-1-thread-3] o.s.i.ip.tcp.TcpOutboundGateway : onMessage: 10.1.3.119:10101:38308:430e8a01-3d8a-462a-85a7-00ff6ce70b19(GenericMessage [payload=byte[108], headers={ip_address=10.1.3.119, id=1006fc9a-8be4-3722-3cbb-9250714b47ec, ip_hostname=10.1.3.119, ip_tcp_remotePort=10101, ip_connectionId=10.1.3.119:10101:38308:430e8a01-3d8a-462a-85a7-00ff6ce70b19, timestamp=1447332551117}])
2015-11-12 13:49:11.117 TRACE 10329 --- [pool-1-thread-3] o.s.i.i.tcp.connection.TcpNioConnection : 10.1.3.119:10101:38308:430e8a01-3d8a-462a-85a7-00ff6ce70b19 checking data avail: 0 pending: false
2015-11-12 13:49:11.118 TRACE 10329 --- [pool-1-thread-3] o.s.i.i.tcp.connection.TcpNioConnection : 10.1.3.119:10101:38308:430e8a01-3d8a-462a-85a7-00ff6ce70b19 Nio message assembler exiting... avail: 0
2015-11-12 13:49:11.118 DEBUG 10329 --- [nio-8080-exec-1] o.s.i.ip.tcp.TcpOutboundGateway : Response GenericMessage [payload=byte[108], headers={ip_address=10.1.3.119, id=1006fc9a-8be4-3722-3cbb-9250714b47ec, ip_hostname=10.1.3.119, ip_tcp_remotePort=10101, ip_connectionId=10.1.3.119:10101:38308:430e8a01-3d8a-462a-85a7-00ff6ce70b19, timestamp=1447332551117}]
2015-11-12 13:49:11.118 DEBUG 10329 --- [nio-8080-exec-1] o.s.i.ip.tcp.TcpOutboundGateway : Removed pending reply 10.1.3.119:10101:38308:430e8a01-3d8a-462a-85a7-00ff6ce70b19
有什么想法吗?
这是我的自定义反序列化方法:
@Override
public byte[] deserialize(InputStream inputStream) throws IOException {
if (logger.isDebugEnabled()) {
logger.debug("Available to read:" + inputStream.available());
}
byte[] header = new byte[2];
header[0] = (byte) inputStream.read();
if (header[0] < 0) {
throw new SoftEndOfStreamException("Stream closed between payloads");
}
header[1] = (byte) inputStream.read();
if (header[1] < 0) {
throw new SoftEndOfStreamException("Stream closed between payloads");
}
int val = getIntFromTwoBytes(header);
byte[] length = new byte[val];
for (int i = 0; i < val; i++) {
length[i] = (byte) inputStream.read();
}
int messageLength;
if (val == 2) {
messageLength = getIntFromTwoBytes(length);
} else if (val == 4) {
messageLength = getIntFromFourBytes(length);
} else throw new IOException("Unexpected count of bytes that holds message length");
byte[] answer = new byte[messageLength];
for (int i = 0; i < messageLength; i++) {
int bite = inputStream.read();
if (bite < 0) {
throw new SoftEndOfStreamException("Stream closed between payloads");
}
answer[i] = (byte) bite;
}
ByteBuffer b = ByteBuffer.allocate(2 + val + messageLength);
b.put(header);
b.put(length);
b.put(answer);
return b.array();
}
我们使用自己的二进制协议,所以我知道传入消息的确切长度。
答案 0 :(得分:0)
这当然不是意图,但是我看到了,是的,超时被报告给反序列化器作为正常的EOF而不是IOException。
我们的标准原始反序列化器(期望一个套接字接近结束流)表现出这个问题......
fetch first
因为超时被视为EOF并且返回了部分消息(作为休息的结果)。
你的反序列化程序在获得EOF时根本不会检查它是否有部分结果......
if (bite < 0) {
if (n == 0) {
throw new SoftEndOfStreamException("Stream closed between payloads");
}
break;
}
...所以我看不出你的解串器如何表现出这个问题。当我们超时消息时,您的反序列化器应该得到if (bite < 0) {
throw new SoftEndOfStreamException("Stream closed between payloads");
}
,这应该只是导致部分消息被丢弃。
我们需要更改NIO连接,以便反序列化器在超时后获得超时异常,但在这种情况下,反序列化器不应该导致部分消息。
我会看看我是否可以模拟一些数据来处理你的代码并回复你。
修改强>
我没有看到您的反序列化程序的行为,只能使用我们的标准-1
。
我首先用你提供的测试;然后我把它打磨了一下 - 在开始解码数据之后你不应该抛出ByteArrayRawDeserializer
;这应该是一个硬IOException(例如通过调用SoftEndOfStreamException
)。
这是我的精美版本:
checkClosure()