webSocket+netty的简单应用

1.webScoket客户端

@Slf4j
public class MyWebSocketClient extends WebSocketClient {
    private Map<String, String> map;
    public MyWebSocketClient(URI uri,Map<String, String> map) {
        super(uri);
        this.map=map;
    }

    @PostConstruct
    private void init() {
        try {
            this.connectBlocking();
            //开启心跳重连线程
            new Thread(() -> {
                while (true) {
                    try {
                        //当连接状态不为open时每5秒重连一次
                        if (getReadyState() != ReadyState.OPEN) {
                            reconnectBlocking();
                            Thread.sleep(5 * 1000);
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void onOpen(ServerHandshake serverHandshake) {
        log.info("与云服务器成功建立WS连接");
    }

    @Override
    public void onMessage(String s) {
        log.info("接收到来自服务端的消息{}",s);
        ReplyMsg replyMsg = JSONUtil.toBean(s, ReplyMsg.class);
        map.put("sid",replyMsg.getSid());
    }

    @Override
    public void onClose(int code, String reason, boolean remote) {
        log.warn("readyState:" + getReadyState() + "," + code + "-reason:" + reason + ",与云服务器断开了连接");
    }

    @Override
    public void onError(Exception e) {
        log.error("webSocket发生异常: {}:{}", e.getClass().getName(), e.getMessage());
        close();
    }



}

onMessage是接收来自服务端的消息,如果需要向服务端发送消息则可以使用new一个webScoket客户端与服务端立ws链接

 MyWebSocketClient client = new MyWebSocketClient(new URI(this.frontUrl), this.map);
            client.connect();
            while (!client.isOpen()) {
                Thread.sleep(100);
            }
            log.info("连接成功!!!!!!!!!!!!!!");
            //1.发送opt=0的初始数据
            DotMsg dotMsg = opt0();
            String msg = JSONUtil.toJsonStr(dotMsg);
            log.info("发送消息为{}",msg);
            client.send(msg);

2.服务端使用netty是基于NIO实现

导入pom依赖

<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>4.1.79.Final</version>
</dependency>
@Component
public class WsServer {
    @Value("${netty.port:8088}")
    private int port;

    @Value("${netty.bossThread:1}")
    private int bossThread;

    @Value("${netty.workThread:1}")
    private int workThread;

    @Autowired
    private DotMsgHandler msgHandler;

    public void start() {
        NioEventLoopGroup bossGroup = null;
        NioEventLoopGroup workGroup = null;
        try {
            log.info("Starting Websocket Server...");
            // 创建两个线程组,bossGroup为接收请求的线程组,一般1-2个就行
            bossGroup = new NioEventLoopGroup(this.bossThread);
            workGroup = new NioEventLoopGroup(this.workThread);

            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workGroup)
                    // 指定使用的channel
                    .channel(NioServerSocketChannel.class)
                    // 设置连入服务端的 Client 的 SocketChannel 的处理器
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline pipeline = socketChannel.pipeline();
                            // 添加一个http的编解码器,HttpRequestDecoder和HttpResponseEncoder的组合,针对http协议进行编解码
                            pipeline.addLast(new HttpServerCodec());
                            // 添加一个用于支持大数据流的支持,分块对客户端发送数据,防止发送大文件时导致内存溢出,channel.write(new ChunkedFile("test.mkv"))
                            pipeline.addLast(new ChunkedWriteHandler());
                            // 添加一个聚合器,这个聚合器主要是将HttpMessage和HttpContents聚合到一个完成得FullHttpRequest/FullHttpResponse中,
                            pipeline.addLast(new HttpObjectAggregator(1024 * 64));
                            // 聚合websocket的数据帧,因为客户端可能分段向服务端发送数据
                            pipeline.addLast(new WebSocketFrameAggregator(10 * 1024 * 1024));
                            // 需要指定接收请求的路由,服务端向外暴露的web socket端点,当客户端传比较大的对象时,maxFrameSize参数的值需调大
                            pipeline.addLast(new WebSocketServerProtocolHandler("/dot", null, true, 10485760));
                            // 超时机制
                            pipeline.addLast(new IdleStateHandler(60, 0, 0, TimeUnit.SECONDS));
                            // 自定义处理器,处理web socket文本消息
                            pipeline.addLast(new TextHandler(msgHandler));
                            // 自定义处理器,处理web socket二进制消息
                            //pipeline.addLast(new BinaryHandler(msgHandler));
                        }
                    });
           //使用netty应用需要指定服务为异步操作
            ChannelFuture channelFuture = bootstrap.bind(this.port).sync();
            log.info("Websocket Server Started on port: {}", this.port);
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            log.error("websocket InterruptedException!", e);
        } finally {
            workGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }
}

TextHandler是自定义消息处理器需要继SimpleChannelInboundHandler<TextWebSocketFrame>这个类才能作为处理器,重写其中的方法

 /**
     * 客户端与服务器建立连接的时候触发
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.info("建立连接,channel:{}", ctx.channel().id().toString());
        dotMsgHandler.connected(ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info("断开连接,channel:{}", ctx.channel().id().toString());
        dotMsgHandler.disconnected(ctx);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame textWebSocketFrame) throws Exception {
        //log.info("channel {} 收到text数据:{}", ctx.channel().id().toString(), textWebSocketFrame.text());
        //客户端会回复信息
       ctx.channel().writeAndFlush(new TextWebSocketFrame(textWebSocketFrame.text()));
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值