使用两条 Camel 路由可以重现全双工通信:
- 感谢使用
reuseChannel 属性
- 由于这种全双工通信将通过两条不同的 Camel 路由实现,因此必须将
sync 属性设置为 false。
这里是第一条路线:
from("netty4:tcp://{{tcpAddress}}:{{tcpPort}}?decoders=#length-decoder,#string-decoder&encoders=#length-encoder,#bytearray-encoder&sync=false&reuseChannel=true") .bean("myMessageService", "receiveFromTCP").to("jms:queue:<name>")
这第一个路由将创建一个 TCP/IP 消费者,这要归功于服务器套接字(由于属性 clientMode,也可以使用客户端套接字)
由于我们想要重用刚刚创建的连接,因此初始化解码器和编码器非常重要,这要归功于 bean(请参阅更多信息)。这个 bean 将负责使用在第一个路由中创建的Channel 发送数据(Netty Channel 包含一个管道,用于在从 TCP/IP 接收/发送到 TCP/IP 之前解码/编码消息。
现在,我们想要将一些数据发送回连接到第一条路由的消费者(来自)端点的部分。由于经典的生产者端点(to),我们无法做到这一点,我们使用一个 bean 对象:
from("jsm:queue:<name>").bean("myMessageService", "sendToTCP");
这里是 bean 代码:
public class MessageService {
private Channel openedChannel;
public void sendToTCP(final Exchange exchange) {
// opened channel will use encoders before writing on the socket already
// created in the first route
openedChannel.writeAndFlush(exchange.getIn().getBody());
}
public void receiveFromTCP(final Exchange exchange) {
// record the channel created in the first route.
this.openedChannel = exchange.getProperty(NettyConstants.NETTY_CHANNEL, Channel.class);
}
}
当然,
两个路由使用相同的 bean 实例,您需要使用注册表来执行此操作:
SimpleRegistry simpleRegistry = new SimpleRegistry();
simpleRegistry.put("myMessageService", new MessageService());
由于 bean 用于两个不同的异步路由,您将不得不处理一些未执行的情况,例如保护 openChannel 成员的访问,或处理意外断开连接。
这篇文章帮助我找到了这个解决方案:
how-to-send-a-response-back-over-a-established-tcp-connection-in-async-mode-usin
reuseChannel property documentation