前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Netty: WebSocket应用,代码demo

Netty: WebSocket应用,代码demo

作者头像
冷环渊
发布2021-11-22 09:24:11
3130
发布2021-11-22 09:24:11
举报

WebSocket

为什么使用进阶版呢? 新的技术肯定是解决了 技术的问题

Http协议都的缺陷 : 通信只能由客户端发起,需要一种服务端能够主动推送到能力 –websocket

**websocket:**这是一种双向通信的能力 也叫做 : “全双工”

websocket是由浏览器发起的

通常我们使用 http叫做 : 短连接 性能好一点 用 websocket 叫做 : 长连接 复用性高一些 适用于不同场景

这里我们还是使用 http来链连接 只不过 连接之后就传输信息 直到断开为止

应为本质上 http 底层是 tcp 是支持实现全双工的

协议标识符 http://127.0.0.1:8080 ws://127.0.0.1:7777

代码语言:javascript
复制
GET ws://127.0.0.1:7777 HTTP/1.1
Host: 127.0.0.1
Upgrade: websocket    # 升级为ws   
Connection: Upgrade   # 此链接需要升级
Sec-WebSocket-key: client-random-string ...  # 标识加密相关信息

响应结果

代码语言:javascript
复制
HTTP/1.1 101
Upgrade: websocket
Connection: Upgrade

响应码 101 代表本次协议需要更改为websocket

连接建立后,支持文本信息及二进制信息。

Websocket实现的原理: 通过http协议进行连接的建立(握手和回答),建立连接后不再使用http,而tcp自身是支持双向通信的,所以能达到“全双工”的效果。

Websocket 应用demo

服务端代码

代码语言:javascript
复制
public class WebSocketServer {
    public static void main(String[] args) {
        //可以自定义线程的数量
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        // 默认创建的线程数量 = CPU 处理器数量 *2
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .handler(new LoggingHandler())
                //当前连接被阻塞的时候,BACKLOG代表的事 阻塞队列的长度
                .option(ChannelOption.SO_BACKLOG, 128)
                //设置连接保持为活动状态
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                .childHandler(new WebSocketInitialzer());

        try {
            ChannelFuture future = serverBootstrap.bind(7777).sync();
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

}

服务端初始化器

代码语言:javascript
复制
public class WebSocketInitialzer extends ChannelInitializer<Channel> {
    @Override
    protected void initChannel(Channel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        //增加编解码器 的另一种方式
        pipeline.addLast(new HttpServerCodec());
        //    块方式写的处理器 适合处理大数据
        pipeline.addLast(new ChunkedWriteHandler());
        //聚合
        pipeline.addLast(new HttpObjectAggregator(512 * 1024));
        /*
         * 这个时候 我们需要声明我们使用的是 websocket 协议
         * netty为websocket也准备了对应处理器  设置的是访问路径
         * 这个时候我们只需要访问 ws://127.0.0.1:7777/hello 就可以了
         * 这个handler是将http协议升级为websocket  并且使用 101 作为响应码
         * */
        pipeline.addLast(new WebSocketServerProtocolHandler("/hello"));
        pipeline.addLast(new WebSocketHandler());
    }
}

服务端处理器

通信使用的单位叫帧 frame 客户端:发送时将消息切割成多个帧 服务端:接收时,将关联的帧重新组装

代码语言:javascript
复制
/*
 * 泛型 代表的是处理数据的单位
 * TextWebSocketFrame : 文本信息帧
 * */
public class WebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame textWebSocketFrame) throws Exception {
        //可以直接调用text 拿到文本信息帧中的信息
        System.out.println("msg:" + textWebSocketFrame.text());
        Channel channel = ctx.channel();
        //我们可以使用新建一个对象 将服务端需要返回的信息放入其中 返回即可
        TextWebSocketFrame resp = new TextWebSocketFrame("hello client from websocket server");
        channel.writeAndFlush(resp);
    }
}

websocket前端编写

代码语言:javascript
复制
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
head>
<body>
<script>
    var socket;
    //    判断当前浏览器是否支持websocket
    if (!window.WebSocket) {
        alert("不支持websocket")
    } else {
        <!-- 创建websocket 连接对象-->
        socket = new WebSocket("ws://127.0.0.1:7777/hello");
        //设置开始连接的方法
        socket.onopen = function (ev) {
            var tmp = document.getElementById("respText");
            tmp.value = "连接已经开启";
        }
        //设置关闭连接的方法
        socket.onclose = function (ev) {
            var tmp = document.getElementById("respText");
            tmp.value = tmp.value + "\n" + "连接已经关闭";
        }
        //设置接收数据的方法
        socket.onmessage = function (ev) {
            var tmp = document.getElementById("respText");
            tmp.value = tmp.value + "\n" + ev.data;
        }
    }

    function send(message) {
        if (!window.socket) {
            return
        }
        /*
        * 判断socket的状态
        * connecting 正在连接 closing 正在关闭
        * closed 已经关闭或打开连接失败
        * open 连接可以 已经正常通信
        * */
        if (socket.readyState == WebSocket.OPEN) {
            socket.send(message);
        } else {
            alert("连接未开启");
        }
    }
script>

<form onsubmit="return false">
    <textarea name="message" style="height: 400px;width: 400px">textarea>
    <input type="button" value="发送" onclick="send(this.form.message.value)">
    <textarea id="respText" style="height: 400px;width: 400px">textarea>
form>
body>
html>

【客户端】

代码语言:javascript
复制
var ws = new WebSocket("ws://127.0.0.1:7777/hello");
ws.onopen = function(ev){
     ws.send("hello"); //建立连接后发送数据
}

设计一个样式 左右两个各有一个文本框,中间放一个发送按钮。 左侧文本框用来发送数据,右侧文本框用来显示数据。

演示效果

启动服务发送消息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x5A4W08I-1637502634311)(netty学习笔记.assets/image-20211121214953195.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x5A4W08I-1637502634311)(netty学习笔记.assets/image-20211121214953195.png)]

服务器接受到的消息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7cZDuYJ4-1637502634314)(netty学习笔记.assets/image-20211121215024472.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7cZDuYJ4-1637502634314)(netty学习笔记.assets/image-20211121215024472.png)]
小结
  1. websocket 一般用于做可复用连接,http一般做短链接
  2. websocket解决了http连接只能客户端发起的痛点
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-11-21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • WebSocket
    • Websocket 应用demo
      • 演示效果
        • 小结
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档