我必须为RPC通信创建TCP / IP服务器。我一定会使用提供的java lib来处理所有“rpc”的东西。该lib接收包含protobuf数据的HDLC消息。 lib本身使用请求和响应处理程序来处理HDLC和protobuf部分。此lib可用于串行连接以及网络连接。
我们想为此TCP服务器使用netty。调用此lib时,它需要“RPC”方法中的java.io.inputstream
和java.io.outputstream
。
我有一个简单的阻塞设置,我在其中创建一个服务器套接字,并将socket.getInputStream()
和socket.getOutputStream()
传递给RPC方法。接下来我需要向这个rpc对象注册一组(一组)rpc处理程序,并且客户端可以连接并且可以发送数据。对我来说似乎很简单。
我还设置了一个netty“echo”服务器,现在我想将这个RPC库与netty一起使用。我正在努力的是如何将我收到的数据转换为所需的InputStream
以及如何转换RPC lib的OutputStream
,以便它可以发送回客户端。我需要解码器/编码器,还是有更简单的方法可以做到这一点?如果是这样,我如何将ByteBuf
转换为InputStream
并将OutputStream
转换回可以通过网络发送的格式?
答案 0 :(得分:1)
如果您的库具有readPacket方法,则可以将ByteBufInputStream
与ReplayingDecoder
结合使用,这相对容易实现:
public class RPCInputHandler extends ReplayingDecoder<Object> {
RPC upstream = ....;
protected void decode(ChannelHandlerContext ctx, ByteBuf buf) throws Exception {
upstream.readPacket(new ByteBufInputStream(buf));
state(null);
}
}
如果您的上游库使用单独的线程来处理传入的消息,那么您将失去Netty的一个主要优点:大量连接的线程数较少。
public class RPCInputHandler extends SimpleChannelInboundHandler<ByteBuf> {
RPC upstream = ....;
PipedInputStream in;
PipedOutputStream out;
@Override public void channelActive(ChannelHandlerContext ctx) throws Exception {
in = new PipedInputStream();
out = new PipedOutputStream(in);
upstream.startInput(in);
}
@Override public void channelInactive(ChannelHandlerContext ctx) throws Exception {
out.close(); // This sends EOF to the other pipe
}
// This method is called messageReceived(ChannelHandlerContext, I) in 5.0.
public void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
byte[] data = new byte[msg.readableBytes()];
msg.readBytes(data);
out.write(data);
}
}
创建一个将字节写入连接的自定义OutputStream很简单,大多数方法直接映射到
public class OutputStreamNetty extends OutputStream {
final Channel channel = ...;
ChannelFuture lastFuture;
private void checkFuture() throws IOException {
if(lastFuture.isDone()) {
if(lastFuture.cause() != null) {
throw new IOException("Downstream write problem", lastFuture.cause() );
}
lastFuture = null;
}
}
private void addFuture(ChannelFuture f) {
if(lastFuture == null) {
lastFuture = f;
}
}
public void close() throws IOException {
checkFuture()
addFuture(channel.close());
}
public void flush() throws IOException {
checkFuture()
addFuture(channel.flush());
}
public void write(byte[] b, int off, int len) throws IOException {
checkFuture()
Bytebuf f = channel.alloc().buffer(len);
f.writeBytes(b, off, len);
addFuture(channel.write(f));
}
public abstract void write(int b) throws IOException {
checkFuture()
Bytebuf f = channel.alloc().buffer(1);
f.writeByte(b);
addFuture(channel.write(f));
}
}