如何将接收的数据转换为输入流和输出流

时间:2016-01-29 08:06:43

标签: java netty

我必须为RPC通信创建TCP / IP服务器。我一定会使用提供的java lib来处理所有“rpc”的东西。该lib接收包含protobuf数据的HDLC消息。 lib本身使用请求和响应处理程序来处理HDLC和protobuf部分。此lib可用于串行连接以及网络连接。

我们想为此TCP服务器使用netty。调用此lib时,它需要“RPC”方法中的java.io.inputstreamjava.io.outputstream

我有一个简单的阻塞设置,我在其中创建一个服务器套接字,并将socket.getInputStream()socket.getOutputStream()传递给RPC方法。接下来我需要向这个rpc对象注册一组(一组)rpc处理程序,并且客户端可以连接并且可以发送数据。对我来说似乎很简单。

我还设置了一个netty“echo”服务器,现在我想将这个RPC库与netty一起使用。我正在努力的是如何将我收到的数据转换为所需的InputStream以及如何转换RPC lib的OutputStream,以便它可以发送回客户端。我需要解码器/编码器,还是有更简单的方法可以做到这一点?如果是这样,我如何将ByteBuf转换为InputStream并将OutputStream转换回可以通过网络发送的格式?

1 个答案:

答案 0 :(得分:1)

的InputStream

另一个api有一个readpacket()方法

如果您的库具有readPacket方法,则可以将ByteBufInputStreamReplayingDecoder结合使用,这相对容易实现:

public class RPCInputHandler extends ReplayingDecoder<Object> {
   RPC upstream = ....;
   protected void decode(ChannelHandlerContext ctx, ByteBuf buf) throws Exception {
      upstream.readPacket(new ByteBufInputStream(buf));
      state(null);
   }
}

远程api使用线程来读取流

如果您的上游库使用单独的线程来处理传入的消息,那么您将失去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

创建一个将字节写入连接的自定义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));
    }

}