netty整合websocket(完美教程)

websocket的介绍:

WebSocket是一种在网络通信中的协议,它是独立于HTTP协议的。该协议基于TCP/IP协议,可以提供双向通讯并保有状态。这意味着客户端和服务器可以进行实时响应,并且这种响应是双向的。WebSocket协议端口通常是80,443。

WebSocket的出现使得浏览器具备了实时双向通信的能力。与HTTP这种非持久单向响应应答的协议相比,WebSocket是一个持久化的协议。举例来说,即使在关闭网页或者浏览器后,WebSocket的连接仍然保持,用户也可以继续接收到服务器的消息。

此外,要建立WebSocket连接,需要浏览器和服务器握手进行建立连接。一旦连接建立,WebSocket可以在浏览器和服务器之间双向发送或接受信息。总的来说,WebSocket提供了一个高效、实时的双向通信方案。

1、用netty构建websocket服务器

package org.tianfan.websocket;// WebSocketServer.java

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;

public class WebSocketServer {

    private final int port;

    public WebSocketServer(int port) {
        this.port = port;
    }

    public void run() throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
             .channel(NioServerSocketChannel.class)
             .childHandler(new ChannelInitializer<SocketChannel>() {
                 @Override
                 public void initChannel(SocketChannel ch) throws Exception {
                     ChannelPipeline p = ch.pipeline();
                     p.addLast(new HttpServerCodec());
                     p.addLast(new HttpObjectAggregator(65536));
                     p.addLast(new WebSocketServerProtocolHandler("/websocket"));
                     p.addLast(new WebSocketServerHandler());
                 }
             });

            ChannelFuture f = b.bind(port).sync();
            f.channel().closeFuture().sync();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws Exception {
        int port = 8080;
        if (args.length > 0) {
            port = Integer.parseInt(args[0]);
        }

        new WebSocketServer(port).run();
    }
}

我来解释一下上面的代码:

  • p.addLast(new HttpServerCodec()):添加HTTP服务器编解码器,用于将数据转换成HTTP协议格式进行传输。
  • p.addLast(new HttpObjectAggregator(65536)):添加HTTP对象聚合处理器,用于将HTTP请求或响应中的多个消息片段聚合成完整的消息。
  • p.addLast(new WebSocketServerProtocolHandler("/websocket")):添加WebSocket协议处理器,用于处理WebSocket握手、消息传输等操作。
  • p.addLast(new WebSocketServerHandler()):添加WebSocket处理器,用于处理客户端与服务器端之间的数据交换,实现自定义的业务逻辑。

使用Netty框架中的WebSocketServerProtocolHandler处理器,将HTTP升级为WebSocket协议。它创建了一个新的管道(pipeline)并将WebSocket处理程序添加到管道的尾部,以便处理WebSocket协议的握手和帧。"/websocket"是WebSocket的URI路径,它指定了WebSocket服务的相对地址,该地址将在客户端请求连接时被指定。

package org.tianfan.websocket;

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

public class WebSocketServerHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    @Override
    public void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
        // 处理消息
        System.out.println("Received message: " + msg.text());
        ctx.channel().writeAndFlush(new TextWebSocketFrame("Server received: " + msg.text()));
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // 添加连接
        System.out.println("Client connected: " + ctx.channel());
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        // 断开连接
        System.out.println("Client disconnected: " + ctx.channel());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        // 异常处理
        cause.printStackTrace();
        ctx.close();
    }
}

我来解释一下上面的代码:

刚信息发过来的时候,在服务端打印,并写入前端。

2、前端客户端页面:

<!-- index.html -->

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>WebSocket Test</title>
</head>
<body>
    <h1>WebSocket Test</h1>
    <div>
        <input type="text" id="message" placeholder="Message">
        <button onclick="send()">Send</button>
    </div>
    <div id="output"></div>
    <script>
        var socket = new WebSocket("ws://localhost:8080/websocket");

        socket.onopen = function(event) {
            console.log("WebSocket opened: " + event);
        };

        socket.onmessage = function(event) {
            console.log("WebSocket message received: " + event.data);
            var output = document.getElementById("output");
            output.innerHTML += "<p>" + event.data + "</p>";
        };

        socket.onclose = function(event) {
            console.log("WebSocket closed: " + event);
        };

        function send() {
            var message = document.getElementById("message").value;
            socket.send(message);
        }
    </script>
</body>
</html>

运行结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/172892.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Redis:抢单预热

前言 在当今的互联网时代&#xff0c;抢单活动已经成为了电商平台、外卖平台等各种电子商务平台中常见的营销手段。通过抢单活动&#xff0c;商家可以吸引大量用户参与&#xff0c;从而提高销量和知名度。然而&#xff0c;抢单活动所带来的高并发请求往往会给系统带来巨大的压…

opencv-形态学处理

通过阈值化分割可以得到二值图&#xff0c;但往往会出现图像中物体形态不完整&#xff0c;变的残缺&#xff0c;可以通过形态学处理&#xff0c;使其变得丰满&#xff0c;或者去除掉多余的像素。常用的形态学处理算法包括&#xff1a;腐蚀&#xff0c;膨胀&#xff0c;开运算&a…

Spring-IOC-@Import的用法

1、Car.java package com.atguigu.ioc; import lombok.Data; Data public class Car {private String cname; }2、 MySpringConfiguration2.java package com.atguigu.ioc; import org.springframework.context.annotation.Bean; import org.springframework.context.annotatio…

一、防火墙-基础知识

学习防火墙之前&#xff0c;对路由交换应要有一定的认识 1、什么是防火墙2、防火墙的发展史3、安全区域3.1.接口、网络和安全区域的关系3.2.报文在安全区域之间流动方向3.3.安全区域的配置安全区域小实验 3.4.状态检测和会话机制3.4.1.状态检测3.4.2.会话 3.5.状态检测和会话机…

c语言-数据结构-链式二叉树

目录 1、二叉树的概念及结构 2、二叉树的遍历概念 2.1 二叉树的前序遍历 2.2 二叉树的中序遍历 2.3 二叉树的后序遍历 2.4 二叉树的层序遍历 3、创建一颗二叉树 4、递归方法实现二叉树前、中、后遍历 4.1 实现前序遍历 4.2 实现中序遍历 4.3 实现后序遍历 5、…

《算法通关村——最长公共前缀问题解析》

《算法通关村——最长公共前缀问题解析》 14. 最长公共前缀 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀&#xff0c;返回空字符串 ""。 示例 1&#xff1a; 输入&#xff1a;strs ["flower","flow","flight…

腾讯云代金券怎么领取(腾讯云代金券在哪领取)

腾讯云代金券是可抵扣费用的优惠券&#xff0c;领券之后新购、续费、升级腾讯云相关云产品可以直接抵扣订单金额&#xff0c;节省购买腾讯云的费用&#xff0c;本文将详细介绍腾讯云代金券的领取方法和使用教程。 一、腾讯云代金券领取 1、新用户代金券【点此领取】 2、老用户…

Unity中Shader的PBR的基础知识与理论

文章目录 前言一、什么是PBR二、什么是PBS在这里插入图片描述 三、PBS的核心理论1、物质的光学特性&#xff08;Substance Optical Properties&#xff09;2、微平面理论&#xff08;Microfacet Theory&#xff09;3、能量守恒&#xff08;Energy Conservation&#xff09;4、菲…

90%的测试工程师是这样使用Postman做接口测试的...

一&#xff1a;接口测试前准备 接口测试是基于协议的功能黑盒测试&#xff0c;在进行接口测试之前&#xff0c;我们要了解接口的信息&#xff0c;然后才知道怎么来测试一个接口&#xff0c;如何完整的校验接口的响应值。 那么问题来了&#xff0c;那接口信息从哪里获取呢&…

金山云2023年Q3财报:持续向好!

11月21日&#xff0c;金山云公布了2023年第三季度业绩。 财报显示&#xff0c;金山云Q3营收16.3亿元&#xff0c;调整后毛利率达12.1%再创历史新高&#xff0c;调整后毛利额同比上涨57.5%。今年第三季度&#xff0c;公有云实现收入10.2亿元&#xff0c;毛利率达到4.7%&#xf…

STM32出现 Invalid Rom Table 芯片锁死解决方案

出现该现象的原因为板子外部晶振为25M&#xff0c;而程序软件上以8M为输入晶振频率&#xff0c;导致芯片超频锁死&#xff0c;无法连接、下载。 解决方案 断电&#xff0c;将芯片原来通过10k电阻接地的BOOT0引脚直接接3.3V&#xff0c;硬件上置1上电&#xff0c;连接目标板&am…

Redis跳跃表

前言 跳跃表(skiplist)是一种有序数据结构&#xff0c;它通过在每一个节点中维持多个指向其他节点的指针&#xff0c;从而达到快速访问节点的目的。 跳跃表支持平均O(logN)&#xff0c;最坏O(N)&#xff0c;复杂度的节点查找&#xff0c;还可以通过顺序性来批量处理节点…

ROS2中Executors对比和优化

目录 SingleThreadExecutorEventExecutor SingleThreadExecutor 执行流程 EventExecutor 通信图

局域网文件共享神器:Landrop

文章目录 前言解决方案Landrop软件界面手机打开效果 软件操作 前言 平常为了方便传文件&#xff0c;我们都是使用微信或者QQ等聊天软件&#xff0c;互传文件。这样传输有两个问题&#xff1a; 必须登录微信或者QQ聊天软件。手机传电脑还有网页版微信&#xff0c;电脑传手机比…

MT8735/MTK8735安卓核心板规格参数介绍

MT8735核心板是一款高性能的64位Cortex-A53四核处理器&#xff0c;设计用于在4G智能设备上运行安卓操作系统。这款多功能核心板支持LTE-FDD/LTE-TDD/WCDMA/TD-SCDMA/EVDO/CDMA/GSM等多种网络标准&#xff0c;同时还具备WiFi 802.11a/b/g/n和BT4.0LE等无线通信功能。此外&#x…

pipeline传参给job

场景&#xff1a;pipeline实现自动部署&#xff0c;job实现自动测试&#xff0c;但是只有部署dddd环境时&#xff0c;才调自动测试的job&#xff0c;所以需要在调自动测试job时&#xff0c;把参数传给测试job 上一个任务会显示下一步调谁 ------------------------------------…

Redis从入门到精通(三)-高阶篇

文章目录 0. 前言[【高阶篇】3.1 Redis协议(RESP )详解](https://blog.csdn.net/wangshuai6707/article/details/132742584)[【高阶篇】3.3 Redis之底层数据结构简单动态字符串(SDS)详解](https://blog.csdn.net/wangshuai6707/article/details/131101404)[【高阶篇】3.4 Redis…

玩转系统|长亭雷池WAF详细使用教程——深入了解

目录 配置防护站点 界面操作​ 如何配置域名、端口、上游服务器​ 工作原理​ 在单独设备上部署雷池&#xff08;推荐&#xff09;​ 直接在网站服务器上部署雷池​ 和其他反代设备一起部署的情况​ 配置后网站无法访问&#xff0c;如何排查​ 测试防护效果 确认网站…

5-4计算一串字符的空格数字字符其他

#include<stdio.h> int main(){char c;int space0;//空格int letters0;//英文字母int numbers0;//数字int others0;//其他字符printf("请输入一行字符&#xff1a;");while((cgetchar())!\n)//获取字符的内容&#xff0c;到\n停止{if(c>a&&c<z|…

BGP笔记

自治系统----AS AS划分的原因&#xff1a;如果网络太大&#xff0c;路由数量进一步增加&#xff0c;路由表规模变得太大&#xff0c;会导致路由收敛速度变慢&#xff0c;设备性能消耗加大&#xff0c;且全网设备对于路由信息的认知不同&#xff0c;造成流量通讯障碍 AS号&…