Netty客户端无法从非Netty服务器读取响应

时间:2018-12-18 12:31:19

标签: java sockets tcp netty tcp-ip

我有一个Tcp客户端,它连接到旧的大型机(52年),该大型机发送和接收来自它的请求和响应。

这是我客户端的核心连接部分,

public class SimpleConnector {

    private String carrier;
    private SocketChannel socketChannel;
    public static final byte END_OF_MESSAGE_BYTE = (byte) 0x2b;

    public SimpleConnector(String carrier, InetSocketAddress inetSocketAddress) throws IOException {
        this.carrier = this.carrier;
        socketChannel = SocketChannel.open();
        socketChannel.socket().connect(inetSocketAddress, 30000);
    }

    public void shutDown() throws IOException {
        this.socketChannel.close();
    }
    //Send Request
    public String sendRequest(String request) throws Exception {
            final CharsetEncoder charsetEncoder = Charset.forName("ISO-8859-1").newEncoder();
            int requestLength = 12 + request.length() + 1;
            ByteBuffer buffer = ByteBuffer.allocate(requestLength);
            buffer.order(ByteOrder.BIG_ENDIAN);
            buffer.putInt(requestLength);
            buffer.put(charsetEncoder.encode(CharBuffer.wrap(carrier)));
            buffer.put(charsetEncoder.encode(CharBuffer.wrap(request)));
            buffer.put(END_OF_MESSAGE_BYTE);
            buffer.flip();
            socketChannel.write(buffer);
            return readResponse();

    }
    //Read Response
    protected String readResponse() throws Exception {
            CharsetDecoder charsetDecoder = Charset.forName("ISO-8859-1").newDecoder();
            int responseHeaderLength = 12;
            ByteBuffer responseHeaderBuf = ByteBuffer.allocate(responseHeaderLength);
            responseHeaderBuf.order(ByteOrder.BIG_ENDIAN);
            int bytesRead = 0;
            do {
                bytesRead = socketChannel.read(responseHeaderBuf);
            } while (bytesRead!=-1 && responseHeaderBuf.position()<responseHeaderLength);

            if (bytesRead==-1) {
                throw new IOException(carrier + " : Remote connection closed unexpectedly");
            }
            responseHeaderBuf.flip();
            int lengthField = responseHeaderBuf.getInt();
            int responseLength = lengthField - responseHeaderLength;
            responseHeaderBuf.clear();
            ByteBuffer responseBuf = ByteBuffer.allocate(responseLength);
            bytesRead = socketChannel.read(responseBuf);
            if (bytesRead>responseBuf.limit() || bytesRead ==-1) {
                throw new IOException(carrier + " : Remote connection closed unexpectedly");
            }
            responseBuf.flip();
            if (responseBuf.get(responseBuf.limit()-1)==END_OF_MESSAGE_BYTE) {
                responseBuf.limit(responseBuf.limit()-1);
            }
            responseBuf.clear();
            String response = charsetDecoder.decode(responseBuf).toString();
            return response;

    }

    public static void main(String[] args) throws Exception{
        SimpleConnector simpleConnector = new SimpleConnector("carrier",new InetSocketAddress("localhost",9999));
        String response=simpleConnector.sendRequest("Request");
        System.out.println(response);
    }
}

我正在尝试使用Netty重写以下内容。通过参考以下教程。

我面临的问题是我能够连接到服务器,但无法对其进行读写。我正在使用ChannelInboundHandlerAdapter进行读写操作。

这是我的Netty客户

public class NettyClient {
    int port;
    Channel channel;
    EventLoopGroup workGroup = new NioEventLoopGroup();

    public NettyClient(int port){
        this.port = port;
    }

    public ChannelFuture connectLoop() throws Exception {
        try{
            Bootstrap b = new Bootstrap();
            b.group(workGroup);
            b.channel(NioSocketChannel.class);
            b.option(ChannelOption.SO_KEEPALIVE, true);
            b.handler(new ChannelInitializer<SocketChannel>() {
                protected void initChannel(SocketChannel socketChannel) throws Exception {
                    socketChannel.pipeline().addLast(new NettyClientHandler());
                }
            }); 
            ChannelFuture channelFuture = b.connect("remote-ip", this.port).sync();
            this.channel = channelFuture.channel();

            return channelFuture;
        }finally{
        }
    }
    public void shutdown(){
        workGroup.shutdownGracefully();
    }

    public static void main(String[] args) throws Exception{

        try {
            NettyClient nettyClient = new NettyClient(12000);
            ChannelFuture channelFuture = nettyClient.connectLoop();
            System.out.println("Sleep 2sec");
            Thread.sleep(2000);
            String command ="username";
            final Charset charset = Charset.forName("ISO-8859-1");
            int length = 13 + command.length();
            if (channelFuture.isSuccess()) {
                ByteBuf byteBuf = Unpooled.buffer(1024);
                byteBuf.writeInt(length);
                byteBuf.writeCharSequence("Some Info",charset);
                byteBuf.writeCharSequence(command,charset);
               channelFuture.channel().writeAndFlush(byteBuf).addListener(new ListenerImpl());

            }
        }
        catch(Exception e){
            System.out.println(e.getMessage());
            System.out.println("Try Starting Server First !!");
        }
        finally {
        }
    }
private static final class ListenerImpl implements ChannelFutureListener{

    public void operationComplete(ChannelFuture channelFuture) throws Exception {
        if (channelFuture.isSuccess()){
            System.out.println("Success"); //I can see success in Listener after write, but couldn't read response

        }else {
            System.out.println("Failed");
        }
    }
}
}

处理程序

public class NettyClientHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        super.channelReadComplete(ctx);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("NettyClientHandler : channelRead" );
        ByteBuf byteBuf = (ByteBuf) msg;
        String message = byteBuf.toString(Charset.defaultCharset());
        System.out.println("Received Message : " + message);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        System.out.println("NettyClientHandler : channelActive" );
    }
}

我最初以为netty仅适用于netty服务器。但是这个答案清除了我对此的怀疑

Does a Netty client work with a netty server only?

有人可以指导我,我做错了什么吗?

1 个答案:

答案 0 :(得分:2)

我认为问题出在您的ClientHandler上。您应该在建立TCP服务器与客户端之间的连接后调用writeAndFlush()中的channelActive方法。请使用下面的更新代码,看看它是否可以解决问题。

    @Sharable
    public class NettyClientHandler extends SimpleChannelInboundHandler<ByteBuf> {

        @Override
        public void channelRead0(ChannelHandlerContext ctx, ByteBuf byteBuf) throws Exception {
            String message = byteBuf.toString(Charset.defaultCharset());
            System.out.println("Received Message : " + message);
        }

        @Override
        public void channelActive(ChannelHandlerContext channelHandlerContext){
            channelHandlerContext.writeAndFlush(Unpooled.copiedBuffer("Netty Rocks!", CharsetUtil.UTF_8));
        }

    }