netty4 websocket client(带返回结果的客户端)

netty websocket client

netty4 websocket client(带返回结果的客户端)

网上更多的基于netty的websocket服务端的实现,客户端更多的是html,本文介绍自己实现websocket的client,并返回异步返回结果的数据,方便业务逻辑调用。

pom依赖

 
            io.netty
            netty-all
            4.1.35.Final
        
  

ClientInitializer


import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpClientCodec;
import io.netty.handler.codec.http.HttpObjectAggregator;

import java.util.concurrent.CountDownLatch;

public class ClientInitializer extends ChannelInitializer {
    private CountDownLatch latch;
    public ClientInitializer(CountDownLatch latch) {
        this.latch = latch;
    }
    private WebSocketClientHandler handler;

    @Override
    protected void initChannel(SocketChannel sc) throws Exception {
        handler =  new WebSocketClientHandler(latch);
        ChannelPipeline p = sc.pipeline();
        p.addLast(new ChannelHandler[]{new HttpClientCodec(),
                new HttpObjectAggregator(1024*1024*10)});
        p.addLast("websocketHandler", handler);
    }
    public String getServerResult(){
        return handler.getResult();
    }
    public void resetLathc(CountDownLatch latch) {
        handler.resetLatch(latch);
    }
    public void setHandler(WebSocketClientHandler handler){
        this.handler = handler;
    }

WebSocketClientHandler

import io.netty.channel.*;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketHandshakeException;
import io.netty.util.CharsetUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.CountDownLatch;

public class WebSocketClientHandler extends SimpleChannelInboundHandler {
private static final Logger logger = LoggerFactory.getLogger(WebSocketClientHandler.class);

WebSocketClientHandshaker handshaker;
ChannelPromise handshakeFuture;

private CountDownLatch lathc;
private String result;

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

public void handlerAdded(ChannelHandlerContext ctx) {
    this.handshakeFuture = ctx.newPromise();
}

public WebSocketClientHandshaker getHandshaker() {
    return handshaker;
}

public void setHandshaker(WebSocketClientHandshaker handshaker) {
    this.handshaker = handshaker;
}

public ChannelPromise getHandshakeFuture() {
    return handshakeFuture;
}

public void setHandshakeFuture(ChannelPromise handshakeFuture) {
    this.handshakeFuture = handshakeFuture;
}

public ChannelFuture handshakeFuture() {
    return this.handshakeFuture;
}

protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
    System.out.println("channelRead0  " + this.handshaker.isHandshakeComplete());
    Channel ch = ctx.channel();
    FullHttpResponse response;
    if (!this.handshaker.isHandshakeComplete()) {
        try {
            response = (FullHttpResponse) msg;
            //握手协议返回,设置结束握手
            this.handshaker.finishHandshake(ch, response);
            //设置成功
            this.handshakeFuture.setSuccess();
            logger.info("WebSocket Client connected! response headers[sec-websocket-extensions]:{}" + response.headers());
        } catch (WebSocketHandshakeException var7) {
            FullHttpResponse res = (FullHttpResponse) msg;
            String errorMsg = String.format("WebSocket Client failed to connect,status:%s,reason:%s", res.status(), res.content().toString(CharsetUtil.UTF_8));
            this.handshakeFuture.setFailure(new Exception(errorMsg));
        }
    } else if (msg instanceof FullHttpResponse) {
        response = (FullHttpResponse) msg;
        throw new IllegalStateException("Unexpected FullHttpResponse (getStatus=" + response.status() + ", content=" + response.content().toString(CharsetUtil.UTF_8) + ')');
    } else {
        WebSocketFrame frame = (WebSocketFrame) msg;
        if (frame instanceof TextWebSocketFrame) {
            TextWebSocketFrame textFrame = (TextWebSocketFrame) frame;
            //this.listener.onMessage(textFrame.text());
            logger.info("text msg is " + textFrame.text());
            result = textFrame.text();
            lathc.countDown();// 消息接收后释放同步锁,lathc是从Client加一传回来的
        }
    }
}

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

public String getResult() {
    return result;
}

WebSocketCallable

import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.Callable;

public class WebSocketCallable implements Callable {
private static final Logger logger = LoggerFactory.getLogger(WebSocketCallable.class);

private String content;

private Channel channel;

private WebSocketCallable(){

}

public WebSocketCallable(Channel channel, String content){
    this.channel = channel;
    this.content = content;
}
@Override
public String call() throws Exception {
    TextWebSocketFrame frame = new TextWebSocketFrame(content);
    channel.writeAndFlush(frame).addListener(new ChannelFutureListener() {
        public void operationComplete(ChannelFuture channelFuture) throws Exception {
            if(channelFuture.isSuccess()){
                logger.info("callback is success");
            }else if (channelFuture.channel() == null){
                logger.info("callback is failed" + channelFuture.cause().getMessage());
                return;
            }
        }
    });
    return null;
}

WebSocketClient

  private static final Logger logger = LoggerFactory.getLogger(WebSocketClient.class);
    private static ExecutorService executor = Executors.newCachedThreadPool();

    private static String uri ;
    private static CountDownLatch latch;
    private static ClientInitializer clientInitializer;

    private WebSocketClient(){
    }
    public WebSocketClient(String uri){
        this.uri = uri;
        latch = new CountDownLatch(0);
        clientInitializer = new ClientInitializer(latch);
    }

    private static class SingletonHolder {
        static final WebSocketClient instance = new WebSocketClient();
    }
    public static WebSocketClient getInstance(){
        return SingletonHolder.instance;
    }


    public static String pushMsg(String content) throws URISyntaxException, InterruptedException {

        EventLoopGroup group=new NioEventLoopGroup();
        Bootstrap boot=new Bootstrap();
        boot.option(ChannelOption.SO_KEEPALIVE,true)
                .option(ChannelOption.TCP_NODELAY,true)
                .option(ChannelOption.SO_BACKLOG,1024*1024*10)
                .group(group)
                .handler(new LoggingHandler(LogLevel.INFO))
                .channel(NioSocketChannel.class)
                .handler(new ClientInitializer(latch));
        URI websocketURI = new URI(uri);
        HttpHeaders httpHeaders = new DefaultHttpHeaders();
        //进行握手
        WebSocketClientHandshaker handshaker = WebSocketClientHandshakerFactory.newHandshaker(websocketURI, WebSocketVersion.V13, (String)null, true,httpHeaders);
        logger.info("connect to server....");
        final Channel channel=boot.connect(websocketURI.getHost(),websocketURI.getPort()).sync().channel();
        WebSocketClientHandler handler = (WebSocketClientHandler)channel.pipeline().get("websocketHandler");
        handler.setHandshaker(handshaker);
        handshaker.handshake(channel);
        //阻塞等待是否握手成功
        handler.handshakeFuture().sync();
        return sendMsg(channel,handler,content);
    }

    public static String sendMsg(Channel channel,WebSocketClientHandler handler,String content) throws InterruptedException {
          logger.info("send msg:" + content);
          //发起线程发送消息
          executor.submit(new WebSocketCallable(channel, content));
          latch = new CountDownLatch(1);
          clientInitializer.setHandler(handler);
          clientInitializer.resetLathc(latch);
          //等待,当websocket服务端返回数据时唤醒屏障,并返回结果
          latch.await();
         return clientInitializer.getServerResult();

    }

    public static void main(String[] args) throws URISyntaxException, InterruptedException {
        String result = "";
        WebSocketClient webSocketClient = new WebSocketClient("ws://localhost:8088");
        result =webSocketClient.pushMsg("hello websocket"); // 返回结果
        System.out.println("¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥"+ result);
    }

效果
netty4 websocket client(带返回结果的客户端)_第1张图片

你可能感兴趣的:(netty)