netty实现长连接

使用netty实现websocket长连接通信

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。

实现长连接主要代码为

pipeline.addLast(new WebSocketServerProtocolHandler("/websocket"));

这段代码是指在服务端的处理通道上改变服务之间通信的协议

具体的实现如下

@Author bumpworld
/*服务端代码*/
public static void main(String[] args) {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try{
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup,workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            //为通道提供一系列的处理器
                            //使用http的编码和解码器
                            pipeline.addLast(new HttpServerCodec());
                            //因为数据是以块写的,添加ChunkedWriteHandle处理器
                            pipeline.addLast(new ChunkedWriteHandler());

                            /*
                            说明:
                            http数据在传输过程中是分段的,HttpObjectAggregator,就是可以将对个段聚合
                            这就是为什么,当浏览器发送大量数据时,就会发出对此http请求
                             */
                            pipeline.addLast(new HttpObjectAggregator(8192));//8k大小

                            /*
                            WebSocketFrame下有六个子类
                            说明
                            对应websocket, 它的数据是以帧(frame)的形式传递
                            要使用websocket协议 则用ws://   用ws传输协议
                            WebSocketServerProtocolHandle 核心功能是将http协议升级为ws协议 保持长连接
                            参数为请求的地址ws://127.0.0.1:7878/websocket
                            websocket是通过状态码101实现的 101 切换协议 通过Upgrade 消息头通知客户端采用不同的协议来完成这个请求
                             */
                            pipeline.addLast(new WebSocketServerProtocolHandler("/websocket"));

                            //自定义业务的处理器
                            pipeline.addLast(new NettyWebSocketHandle());
                        }
                    });
            ChannelFuture sync = bootstrap.bind(7878).sync();
            sync.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

服务端处理器

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;

import java.time.LocalDateTime;
//TextWebSocketFrame 因为websocket是使用帧传输,所以传输类型要是WebSocketFrame类型的
public class NettyWebSocketHandle extends SimpleChannelInboundHandler<TextWebSocketFrame> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
        System.out.println(msg.text());
        ctx.writeAndFlush(new TextWebSocketFrame("服务端收到消息 "+ LocalDateTime.now()+" "+msg.text()));
    }


    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        System.out.println("连接到浏览器:"+ctx.channel().id().asLongText());
        System.out.println("连接到浏览器:"+ctx.channel().id().asShortText());
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        System.out.println("浏览器断开连接:"+ctx.channel().id().asLongText());
        System.out.println("浏览器断开连接:"+ctx.channel().id().asShortText());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("发生异常");
        ctx.close();
    }
}

前端测试
我们用一段简单的代码测试即可

<script>
    var socket;
    if(window.WebSocket){
        socket = new WebSocket("ws://127.0.0.1:7878/websocket");

        socket.onmessage = function (ev) {
            var tr = document.getElementById("resultMsg");
            tr.value = tr.value+"\n"+ev.data;
        };

        socket.onopen = function (ev) {
            var tr = document.getElementById("resultMsg");
            tr.value = ev.data + " :成功建立连接";
        };
        socket.onclose = function (ev) {
            var tr = document.getElementById("resultMsg");
            tr.value = tr.value+"\n"+"断开连接";
        };

        function send(msg) {
            if(!window.socket){
                //不支持websocket
                return;
            }
            if(socket.readyState == WebSocket.OPEN){
                //是否已连接
                socket.send(msg);
            }
        }
    }else {
        alert("你的浏览器不支持websocket服务");

    }
</script>
<form id="form" onsubmit="return false">
    <textarea name="sendMsg" id="sendMsg" style="width: 500px;height: 300px"></textarea>
    <input type="button" value="发送" onclick="send(this.form.sendMsg.value)">
    <textarea id="resultMsg" style="width: 500px;height: 300px"></textarea>
    <input type="button" value="清空内容" onclick="document.getElementById('resultMsg').value = ''">
</form>

效果
在这里插入图片描述

这样 一个基本的实现就差不多完成了 ()

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值