netty客户端同步请求实现

netty客户端同步请求实现


在项目开发中经常会遇到某个请求需要立刻返回结果的请,而我们使用的框架netty是异步的,如何做到同步请求是经常会困惑到刚刚接触netty的同行。
本文使用netty4为标准实现客户端向服务器的同步请求实例。如有不合理之处望各位指正,共同进步。

客户端 SimpleChatClientHandler

package com.netty.chart;

import java.util.concurrent.CountDownLatch;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleStateEvent;

public class SimpleChatClientHandler extends SimpleChannelInboundHandler {

    private CountDownLatch lathc;

    public SimpleChatClientHandler(CountDownLatch lathc) {
        this.lathc = lathc;
    }

    private String result;

    @Override
    protected void channelRead0(ChannelHandlerContext arg0, String arg1) throws Exception {
        System.out.println("==========收到服务器消息:"+arg1);
        result = arg1;
        lathc.countDown();//消息收取完毕后释放同步锁
    }

    public void resetLatch(CountDownLatch initLathc){
        this.lathc = initLathc;
    }

    public String getResult() {
        return result;
    }

     @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        // IdleStateHandler 所产生的 IdleStateEvent 的处理逻辑.
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent e = (IdleStateEvent) evt;
            switch (e.state()) {
                case ALL_IDLE:
                    handleAllIdle(ctx);
                    break;
                default:
                    break;
            }
        }
    }

    protected void handleAllIdle(ChannelHandlerContext ctx) {
//        ctx.channel().writeAndFlush("1" + "\r\n");
    }

}

客户端 SimpleChatClientInitializer

package com.netty.chart;

import java.util.concurrent.CountDownLatch;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.timeout.IdleStateHandler;

public class SimpleChatClientInitializer extends ChannelInitializer {

    private CountDownLatch lathc;

    public SimpleChatClientInitializer(CountDownLatch lathc) {
        this.lathc = lathc;
    }

    private SimpleChatClientHandler handler;

    @Override
    protected void initChannel(SocketChannel channel) throws Exception {
        handler =  new SimpleChatClientHandler(lathc);
        ChannelPipeline pipeline = channel.pipeline();
        pipeline.addLast(new IdleStateHandler(0, 0, 5));
        pipeline.addLast("framer", new DelimiterBasedFrameDecoder(81920, Delimiters.lineDelimiter()));
        pipeline.addLast("decoder", new StringDecoder());
        pipeline.addLast("encoder", new StringEncoder());
        pipeline.addLast("handler", handler);
    }

    public String getServerResult(){
        return handler.getResult();
    }
    //重置同步锁
    public void resetLathc(CountDownLatch initLathc) {
        handler.resetLatch(initLathc);
    }

}

客户端 SimpleChatClient

package com.netty.chart;

import java.util.concurrent.CountDownLatch;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.Delimiters;

public class SimpleChatClient {

    private final String host;
    private final int port;

    public SimpleChatClient(String host, int port) {
        this.host = host;
        this.port = port;
    }

    public void run() throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            CountDownLatch lathc = new CountDownLatch(1);
            SimpleChatClientInitializer clientInitializer = new SimpleChatClientInitializer(lathc);
            Bootstrap bootstrap = new Bootstrap().group(group).channel(NioSocketChannel.class)
                    .handler(clientInitializer);
            ChannelFuture connect = bootstrap.connect(host, port);
            Channel channel = connect.sync().channel();
//          BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
                channel.write("bbbbbb啊啊啊" + "\r\n");
//              connect.awaitUninterruptibly();
//              Void void1 = connect.getNow();
//              System.out.println(void1.toString());
                channel.flush();
                lathc.await();//开启等待会等待服务器返回结果之后再执行下面的代码
                System.out.println("服务器返回 1:" + clientInitializer.getServerResult());

                Thread.sleep(30000);

                lathc = new CountDownLatch(1);//此处为控制同步的关键信息,注意此对象的流转
                clientInitializer.resetLathc(lathc);
                channel.write("bbbbbb啊啊啊1111" + "\r\n");
                channel.flush();
                lathc.await();
                System.out.println("服务器返回 2:" + clientInitializer.getServerResult());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
//          group.shutdownGracefully();
        }
    }


    public static void main(String[] args) throws Exception {
        new SimpleChatClient("127.0.0.1", 8888).run();
    }
}

本文的服务端使用的是官方文档上的demo,如果需要请参考netty实现实时聊天

你可能感兴趣的:(netty)