简体   繁体   English

Netty(4)客户端服务器在同一TCP会话中的通信

[英]Netty (4) client server communication in the same TCP Session

I need to build a client that initiates a TCP connection with a server and upon response it sends a hand shake request every 10 seconds and gets a response from the server. 我需要构建一个客户端来启动与服务器的TCP连接,并在响应时每10秒发送一次握手请求并从服务器获得响应。 The server will be able to send another type of request which my client needs to read and act upon. 服务器将能够发送我的客户需要阅读并对其采取行动的另一种类型的请求。 I am using netty 4.0.26.Final. 我正在使用netty 4.0.26.Final。

I have built a client and a dummy server but I am facing an issue which possibly means that there is something I have not understood. 我已经建立了一个客户端和一个虚拟服务器,但是我面临一个问题,这可能意味着有些事情我还不了解。

My Client: 我的客户:

    String host = "localhost";
    int port = 9884;
    EventLoopGroup workerGroup = new NioEventLoopGroup();

    try {
        Bootstrap b = new Bootstrap();
        b.group(workerGroup);
        b.channel(NioSocketChannel.class);
        b.option(ChannelOption.SO_KEEPALIVE, true);
        b.handler(new MyChannelPipeline());

        // Start the client.
        ChannelFuture f = b.connect(host, port).sync();

        String line = "line";
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        while (!line.equals("exit")) {
            line = in.readLine();
            if (line == null) {
                break;
            }
        }

        // Wait until the connection is closed.
        f.channel().closeFuture().sync();

    } finally {
        workerGroup.shutdownGracefully();
    }

The ChannelPipleline: ChannelPipleline:

    @Override
public void initChannel(Channel ch) throws Exception {

    ChannelPipeline channelPipeline = ch.pipeline();

    //Encodes every request send from the client to the server
    channelPipeline.addLast("clientRequestEncoder", new ClientRequestEncoder());

    //Implements channelActive and exceptionCaught
    channelPipeline.addLast("initialRequestHandler", new InitialRequestHandler());

    channelPipeline.addLast("byteArrayDecoder", new ByteArrayDecoder());

    channelPipeline.addLast("serverResponseDecoder", new ServerResponseDecoder());
    channelPipeline.addLast("serverRequestDecoder", new ServerRequestDecoder());

    //Reads the responses from the client requests AND
    //reads the inbound requests from the server - Implements channelRead 
    //and exceptionCaught
    channelPipeline.addLast("myResponseHandler", new MyResponseHandler());


}

The problem is that when I flush the response to the server (in MyResponseHandler) and exception is caught in InitialRequestHandler: 问题是当我刷新对服务器的响应(在MyResponseHandler中)并且在InitialRequestHandler中捕获了异常时:

ERROR=java.lang.UnsupportedOperationException:unsupported message type: ServerResponse (expected: ByteBuf, FileRegion) ERROR = java.lang.UnsupportedOperationException:不支持的消息类型:ServerResponse(预期:ByteBuf,FileRegion)

I don't see why the response is not flushed back to the server while the hand shake request is always properly flushed. 我看不到为什么总是始终正确刷新了握手请求却没有将响应刷新回服务器的原因。 In both write and flush I have used a ChannelFuture and onOperationComplete this listener f.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); 在写和刷新中,我都使用了ChannelFuture和onOperationComplete来完成此监听器f.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); is fired on failure. 因失败而被解雇。

Can I use two handlers in the same pipeline or is it bad practise? 我可以在同一个管道中使用两个处理程序,还是不好的做法? Moreover how should I fire an unregister event triggered by user input? 此外,我应该如何触发由用户输入触发的注销事件?

I solved this using one Handler that overrides channelActive and channelRead and I rearranged the encoders and decoders properly. 我使用一个覆盖channelActive和channelRead的处理程序解决了此问题,并正确地重新排列了编码器和解码器。 I also solved the "unregister event triggered by user input" this way: 我还通过这种方式解决了“由用户输入触发的注销事件”:

    String line = "line";
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    do {
        logger.info("You typed: " + line + ". Please type 'exit' to terminate the program!");
        line = in.readLine();
    } while (!line.equals("exit"));
    logger.info("You typed: " + line + ". Please wait until the application is successfully shutdown...");

    f.addListener(new ChannelFutureListener() {
        public void operationComplete(ChannelFuture future) throws Exception {
            myChannelPipeline.getMyClientHandler().sendDisconnectRequest(future);
        }
    });

In sendDisconnectReqeust I send the final request and when I get the final response (in channelRead of MyHandler) I call disconnect on the pipeline: 在sendDisconnectReqeust中,我发送最终请求,当得到最终响应时(在MyHandler的channelRead中),我在管道上调用断开连接:

    ChannelPromise cp = new DefaultChannelPromise(ctx.channel());
    ctx.channel().pipeline().disconnect(cp);

However I still have other issues with inbound requests that are never received by my client. 但是,我的客户端从未收到过入站请求的其他问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM