使用netty搭建Websocket客户端


WebSocketClient.class

package chnsoft.beliefflight.net.websocket;

import java.net.URI;
import java.net.URISyntaxException;

import chnsoft.beliefflight.Logger.LogProcess;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.ChannelPromise;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.DefaultHttpHeaders;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpClientCodec;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketHandshakeException;
import io.netty.handler.codec.http.websocketx.WebSocketVersion;
import io.netty.util.CharsetUtil;

public class WebSocketClient
{
    public static final String _Tag = WebSocketClient.class.getSimpleName();
    private final URI uri;
    private Channel channel;

    public WebSocketClient(String url) throws URISyntaxException
    {
        this.uri = new URI(url);
        LogProcess.GetInstance().info(_Tag, "ws地址:" + uri.getHost() + ",端口:" + uri.getPort() + ",详细地址:" + uri.getPath());
    }

    public void connect()
    {
        NioEventLoopGroup group = new NioEventLoopGroup();
        WebSocketClientHandshaker handshaker = WebSocketClientHandshakerFactory.newHandshaker(uri, WebSocketVersion.V13, null, true, new DefaultHttpHeaders());
        WebSocketClientHandler handler = new WebSocketClientHandler(handshaker);
        try
        {
            // 添加管道 绑定端口 添加作用域等
            Bootstrap bootstrap = new Bootstrap().group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>()
            {
                @Override
                protected void initChannel(SocketChannel socketChannel)
                {
                    ChannelPipeline pipeline = socketChannel.pipeline();
                    pipeline.addLast(new HttpClientCodec());
                    pipeline.addLast(new HttpObjectAggregator(8192));
                    // pipeline.addLast(WebSocketClientCompressionHandler.INSTANCE);    因为接了这行代码导致接收不到服务端数据
                    pipeline.addLast(handler);
                }

            });
            // 启动连接
            channel = bootstrap.connect(uri.getHost(), uri.getPort()).sync().channel();
            // 等待握手响应
            handler.handshakeFuture().sync();

        }
        catch (Exception e)
        {
            LogProcess.GetInstance().error(_Tag, "创建连接失败:" + e.getMessage());
        }
    }

    public void sendMessage(String message)
    {
        if (channel != null && channel.isActive())
        {
            channel.writeAndFlush(new TextWebSocketFrame(message));
        }
    }

    public void close() throws InterruptedException
    {
        if (channel != null && channel.isActive())
        {
            channel.close().sync();
        }
    }

    private class WebSocketClientHandler extends SimpleChannelInboundHandler<Object>
    {
        /**
         * 连接处理器
         */
        private final WebSocketClientHandshaker webSocketClientHandshaker;
        /**
         * netty提供的数据过程中的数据保证
         */
        private ChannelPromise handshakeFuture;

        public WebSocketClientHandler(WebSocketClientHandshaker webSocketClientHandshaker)
        {
            this.webSocketClientHandshaker = webSocketClientHandshaker;
        }


        public ChannelFuture handshakeFuture()
        {
            return handshakeFuture;
        }

        /**
         * 当客户端主动链接服务端的链接后,调用此方法
         * @param ctx ChannelHandlerContext
         */
        @Override
        public void channelActive(ChannelHandlerContext ctx)
        {
            webSocketClientHandshaker.handshake(ctx.channel());
        }

        /**
         * ChannelHandler添加到实际上下文中准备处理事件,调用此方法
         * @param ctx ChannelHandlerContext
         */
        @Override
        public void handlerAdded(ChannelHandlerContext ctx)
        {
            handshakeFuture = ctx.newPromise();
        }

        /**
         * 链接断开后,调用此方法
         *
         * @param ctx ChannelHandlerContext
         */
        @Override
        public void channelInactive(ChannelHandlerContext ctx)
        {
            LogProcess.GetInstance().info(_Tag, "websocket连接断开");
            connect();
        }

        /**
         * 接收消息,调用此方法
         */
        @Override
        protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object msg)
        {
            // 处理接收到的WebSocketFrame
            LogProcess.GetInstance().info(_Tag, "接收到UWB数据:" + msg);
            //是否直接解析json数据?

            if (!webSocketClientHandshaker.isHandshakeComplete())
            {
                try
                {
                    //连接建立成功,握手完成
                    webSocketClientHandshaker.finishHandshake(channelHandlerContext.channel(), (FullHttpResponse) msg);
                    //连接完成
                    handshakeFuture.setSuccess();
                    LogProcess.GetInstance().info(_Tag, "websocket已经建立连接");
                }
                catch (WebSocketHandshakeException e)
                {
                    LogProcess.GetInstance().info(_Tag, "websocket连接失败!");
                    handshakeFuture.setFailure(e);
                }
                return;
            }
            if (msg instanceof FullHttpResponse)
            {
                FullHttpResponse response = (FullHttpResponse) msg;
                throw new IllegalStateException("Unexpected FullHttpResponse (getStatus=" + response.status() + ", content=" + response.content().toString(CharsetUtil.UTF_8) + ')');
            }
            this.handleWebSocketFrame(msg);

        }

        /**
         * 处理http连接请求.<br>
         * @param msg:
         */
        private void handleHttpRequest(Object msg)
        {
            webSocketClientHandshaker.finishHandshake(channel, (FullHttpResponse) msg);
            handshakeFuture.setSuccess();
        }

        /**
         * 处理文本帧请求.<br>
         * @param msg 消息
         */
        private void handleWebSocketFrame(Object msg)
        {
            WebSocketFrame frame = (WebSocketFrame) msg;
            if (frame instanceof TextWebSocketFrame)
            {
                TextWebSocketFrame textFrame = (TextWebSocketFrame) frame;
                // ...自定义
                String context = textFrame.text();
                LogProcess.GetInstance().info(_Tag, "收到消息:" + context);
            }
            else if (frame instanceof CloseWebSocketFrame)
            {
                LogProcess.GetInstance().info(_Tag, "连接收到关闭帧");
                channel.close();
            }
        }
    }
}

调用方式:

webSocketClient = new WebSocketClient("ws://192.168.43.117:8181/cs/v1/data/realtime");
//            webSocketClient = new WebSocketClient("ws://192.168.43.117:8080/");
WebSocketClient("ws://192.168.43.22:8181/cs/v1/data/realtime");
            ThreadPoolUtils.execute(() -> {
                try
                {
                    webSocketClient.connect();
                  
                }
                catch (Exception e)
                {
                    LogProcess.GetInstance().error(_Tag, "创建websocket连接失败:" + e.getMessage());
                }
            });

 本文参考:【netty客户端】通过netty实现封装websocket客户端_netty websocket客户端-优快云博客

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值