netty的websocket服务端开发

netty整合websocket(完美教程) WebSocket是一种在网络通信中的协议,它是独立于HTTP协议的。该协议基于TCP/IP协议,可以提供双向通讯并保有状态。这意味着客户端和服务器可以进行实时响应,并且这种响应是双向的。WebSocket协议端口通常是80,443。WebSocket的出现使得浏览器具备了实时双向通信的能力。与HTTP这种非持久单向响应应答的协议相比,WebSocket是一个持久化的协议。举例来说,即使在关闭网页或者浏览器后,WebSocket的连接仍然保持,用户也可以继续接收到服务器的消息。 阅读详情

前两篇文章分析了node.js版本的socket.io的服务端与客户端的代码,其实他们socket.io就是在websocket的基础上进一步做了一层封装,添加了一些心跳,重连接。。。

这篇文章就先来看看在netty中是如何建立websocket服务端的吧,先来回顾一下websocket建立连接以及通信的过程:

(1)客户端向服务端发送http报文格式的请求,而且是GET方法的请求,不过这里与普通的http请求有稍微不同的地方,那就是头部connection字段是Upgrade,然后又Upgrad字段,值是websocket,其请求格式如下:

     * GET /chat HTTP/1.1
     * Host: server.example.com
     * Upgrade: websocket
     * Connection: Upgrade
     * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
     * Sec-WebSocket-Origin: http://example.com
     * Sec-WebSocket-Protocol: chat, superchat
     * Sec-WebSocket-Version: 13

(2)由服务器端向客户端返回特定格式的http报文,表示当前websocket建立,报文格式如下:

     * HTTP/1.1 101 Switching Protocols
     * Upgrade: websocket
     * Connection: Upgrade
     * Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
     * Sec-WebSocket-Protocol: chat

(3)当连接建立以后,那么双方就可以通过刚刚建立连接用的socket来发送数据了,这里发送的数据必须经过websocket的帧格式的编码,具体它的信息就去看websocket的协议标准就知道了。。。


其实知道了整个建立连接以及通信的过程,那么就能够知道如何在channel的pipeline上面安排各种handler的顺序了,如下:

(1)首先要安排http报文的decode,aggregator以及encode的handler,因为最开始还是采用http通信的

(2)接收到websocket的建立连接报文之后,通过一些处理按照规定的格式将http返回发送给客户端,那么这就表示websocket的连接已经建立了

(3)移除前面设置的所有的http报文处理的handler,然后加上websocket的frame的decode以及encodehandler,用于将从客户端收到的数据转化为封装好的格式,以及将要发送的数据转化成byte.


那么接下来来看看具体是如何在netty中建立websocket的服务端的吧,直接上主程序的代码:

public class Fjs {
	public void run() throws Exception {
		EventLoopGroup bossGroup = new NioEventLoopGroup();   //这个是用于serversocketchannel的eventloop
		EventLoopGroup workerGroup = new NioEventLoopGroup();    //这个是用于处理accept到的channel
		try {
			ServerBootstrap b = new ServerBootstrap();    //构建serverbootstrap对象
			b.group(bossGroup, workerGroup);   //设置时间循环对象,前者用来处理accept事件,后者用于处理已经建立的连接的io
			b.channel(NioServerSocketChannel.class);   //用它来建立新accept的连接,用于构造serversocketchannel的工厂类
			
			
			b.childHandler(new ChannelInitializer<SocketChannel>(){      //为accept channel的pipeline预添加的inboundhandler
				@Override     //当新连接accept的时候,这个方法会调用
				protected void initChannel(SocketChannel ch) throws Exception {
					
					//ch.pipeline().addLast(new ReadTimeoutHandler(10));
					//ch.pipeline().addLast(new WriteTimeoutHandler(1));
					
					ch.pipeline().addLast("decoder", new HttpRequestDecoder());   //用于解析http报文的handler
					ch.pipeline().addLast("aggregator", new HttpObjectAggregator(65536));   //用于将解析出来的数据封装成http对象,httprequest什么的
					ch.pipeline().addLast("encoder", new HttpResponseEncoder());   //用于将response编码成httpresponse报文发送
					ch.pipeline().addLast("handshake", new WebSocketServerProtocolHandler("", "", true));  //websocket的handler部分定义的,它会自己处理握手等操作
					//ch.pipeline().addLast("chunkedWriter", new ChunkedWriteHandler());
					//ch.pipeline().addLast(new HttpHanlder());
					ch.pipeline().addLast(new WebSocketHandler());
				}
				
			});
			//bind方法会创建一个serverchannel,并且会将当前的channel注册到eventloop上面,
			//会为其绑定本地端口,并对其进行初始化,为其的pipeline加一些默认的handler
			ChannelFuture f = b.bind(80).sync();    
			f.channel().closeFuture().sync();  //相当于在这里阻塞,直到serverchannel关闭
		} finally {
			bossGroup.shutdownGracefully();
			workerGroup.shutdownGracefully();
		}
	}
	
	public static void main(String args[]) throws Exception {
		new Fjs().run();
	}
}

这里可以看看在channel上面安排的handler的情况,主要是就是http部分的decode以及encode的handler,另外这里有一个比较重要的handler,WebSocketServerProtocolHandler它对整个websocket的通信进行了初始化,包括握手,以及以后的一些通信控制。。。

然后再来看看我们自己定义的handler的处理吧:

	@Override
	public void channelRead(final ChannelHandlerContext ctx, Object msg)
			throws Exception {
		// TODO Auto-generated method stub
		
		WebSocketFrame frame = (WebSocketFrame)msg;
		ByteBuf buf = frame.content();  //真正的数据是放在buf里面的
		
		
		String aa = buf.toString(Charset.forName("utf-8"));  //将数据按照utf-8的方式转化为字符串
		System.out.println(aa);
		WebSocketFrame out = new TextWebSocketFrame(aa);  //创建一个websocket帧,将其发送给客户端
		ctx.pipeline().writeAndFlush(out).addListener(new ChannelFutureListener(){

			@Override
			public void operationComplete(ChannelFuture future)
					throws Exception {
				// TODO Auto-generated method stub
				ctx.pipeline().close();  //从pipeline上面关闭的时候,会关闭底层的chanel,而且会从eventloop上面取消注册
			}
			
		});
		
	}


其实这里也就主要是channelRead方法,将从客户端发送过来的数据读出来输出,然后在返回一个字符串就好了。。。还是比较的简单。。


上面的两段代码就基本上能够使用netty来建立websocket规范的服务端了,可以看到整个用法还是很简单的,这里还有必要去看看WebSocketServerProtocolHandler做了些什么事情。。。

    //当当前这个handler被添加到pipeline之后会调用这个方法
    public void handlerAdded(ChannelHandlerContext ctx) {
        ChannelPipeline cp = ctx.pipeline();
        if (cp.get(WebSocketServerProtocolHandshakeHandler.class) == null) {
            // 这里相当于要在当前的handler之前添加用于处理websocket建立连接时候的握手handler
            ctx.pipeline().addBefore(ctx.name(), WebSocketServerProtocolHandshakeHandler.class.getName(),
                    new WebSocketServerProtocolHandshakeHandler(websocketPath, subprotocols, allowExtensions));
        }
    }

首先可以看到它覆盖了这个方法,那么在当前这个handler加入pipeline之后会在这个pipeline之前添加另外一个handler,这个handler是用于websocket的握手的。。。

好吧,那么我们来看看这个用于websocket建立连接的握手的handler是怎么个用法吧:

    @Override
    public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception {
        FullHttpRequest req = (FullHttpRequest) msg;
        if (req.getMethod() != GET) {  //如果不是get请求,那么就出错了
            sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, FORBIDDEN));
            return;
        }
        //创建爱你websocket进行连接握手的工厂类,因为不同版本的连接握手不太一样
        final WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
                getWebSocketLocation(ctx.pipeline(), req, websocketPath), subprotocols, allowExtensions);
        final WebSocketServerHandshaker handshaker = wsFactory.newHandshaker(req);  //这里会根据不同的websocket版本来安排不同的握手handler
        if (handshaker == null) {
            WebSocketServerHandshakerFactory.sendUnsupportedWebSocketVersionResponse(ctx.channel());
        } else {
        	//其实这里在将用于建立连接的http报文发送回去之后,会将前面添加的http部分的handler都移除,然后加上用于decode和encode针对websocket帧的handler
            final ChannelFuture handshakeFuture = handshaker.handshake(ctx.channel(), req);   //这里说白了就是进行握手,向客户端返回用于建立连接的报文
            handshakeFuture.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    if (!future.isSuccess()) {
                        ctx.fireExceptionCaught(future.cause());
                    } else {
                        ctx.fireUserEventTriggered(  //用于激活握手已经完成的事件,可以让用户的代码收到通知
                                WebSocketServerProtocolHandler.ServerHandshakeStateEvent.HANDSHAKE_COMPLETE);
                    }
                }
            });
            WebSocketServerProtocolHandler.setHandshaker(ctx, handshaker);  //保存当前的shaker
            ctx.pipeline().replace(this, "WS403Responder",
                    WebSocketServerProtocolHandler.forbiddenHttpRequestResponder());  //将当前这个handler替换,因为只有刚开始使用http协议进行通信,接下来就没有了
        }
    }

其实基本还是很简单的,无非就是根据收到的http请求,获取当前建立连接的websocket客户端的版本信息,然后通过版本获取相应的用于握手的handler,然后进行相应的处理,将用于建立websocket连接的报文发送给客户端就可以了,不过这里还有一些细节,那就是会在之后将处理http的handler移除,换成处理websocket帧的handler,因为以后的通信就不是按照http来的了,而且会将当前这个handler也替换掉,毕竟以后就不会再用了嘛。。

那么接下来回到WebSocketServerProtocolHandler,因为本身它是一个messagetomessagedecoder,那么来看看它的decode方法:

    protected void decode(ChannelHandlerContext ctx, WebSocketFrame frame, List<Object> out) throws Exception {
        if (frame instanceof CloseWebSocketFrame) {  //如果是用于关闭
            WebSocketServerHandshaker handshaker = getHandshaker(ctx);
            frame.retain();
            handshaker.close(ctx.channel(), (CloseWebSocketFrame) frame); //发送用于关闭的websocket帧
            return;
        }
        super.decode(ctx, frame, out);  
    }

上面获取的shaker是在前面保存的,毕竟不同版本的websocket对应不同的。。。再来看看它父类的方法吧:

    protected void decode(ChannelHandlerContext ctx, WebSocketFrame frame, List<Object> out) throws Exception {
        if (frame instanceof PingWebSocketFrame) {
            frame.content().retain();
            ctx.channel().writeAndFlush(new PongWebSocketFrame(frame.content()));
            return;
        }
        if (frame instanceof PongWebSocketFrame) {
            // Pong frames need to get ignored
            return;
        }

        out.add(frame.retain());
    }

那么到这里,整个websocket在netty中建立服务端的流程都已经很清楚了。。。

以后如果有时间的自己写一个socket.io的吧,因为现在看到的那些都不太好用的样子。。。

SpringBoot集成netty实现websocket通信 netty实现websocket通信 阅读详情

相关推荐

Netty Websocket

Netty 是一个高性能、异步事件驱动的网络应用程序框架,支持快速开发可维护的高性能协议服务器和客户端。它基于 Java NIO(非阻塞 I/O)进行封装,提供了更简单易用的 API,并解决了 NIO 编程中常见的复杂性和错误。

王小工小工历程 2108

基于 Netty 搭建 WebSocket 集群实现服务器消息推送

本文内容是构建高性能、高可用消息推送的经典案例,在微服务 Spring Cloud 环境下基于 Netty 搭建 websocket 集群实现的。目录为:1、背景2、websocket3、...

公众号:Java后端 8905

netty学习:基于WebSocket协议开发服务端及客户端,实现双向通信

学习过程中有参考Redisson和RocketMq对于netty的使用 一、服务端 1、启动类 @Autowired private WebsocketProperties properties; @Autowired private WebSocketChannelInitializer webSocketChannelInitializer; NioEventLoopGroup bossGroup = new NioEventLoopGroup();

psy_ing的博客 568

Netty网络编程(六):搭建websocket服务器

websocket是一个优秀的协议,它是建立在TCP基础之上的,兼容HTTP的网络协议。通过Websocket我们可以实现客户端和服务器端的即时通讯,免除了客户端多次轮循带来的性能损耗。既然websocket这么优秀,那么怎么在netty中使用websocket呢?

Java+GO+JS全栈工程师-鹤冲天的博客:编程辅导~商务合作~技术交流 1万+

Netty实现WebSocket服务端与客户端交互技巧总结

WebSocket是一种在单个TCP连接上进行全双工通信的协议。与传统HTTP轮询不同,WebSocket允许服务器主动向客户端发送消息,大幅提升了实时通信的效率。它通过升级HTTP协议的方式建立长连接,实现了真正的双向通信。

weixin_36364707的博客 1163

做量化没有实时数据怎么行?我找到一个超级好用的Python库,速度还贼快!

今天咱们介绍了 pytdx 这个神奇的库,重点包括:✅ 安装 pytdx✅ 连接 TDX 服务器✅ 获取实时行情数据✅ 获取 K 线数据✅ 获取分笔成交数据总之,pytdx 是一个速度快、免费、易用的量化利器,适合 A 股量化交易的同学们使用。如果你还在为数据发愁,赶紧试试吧!🚀顺手再看就是对花姐最大的支持,期待你的关注。

奔跑的蜗牛 5720

spring netty websocket 服务端开发

场景 需求: 由于公司是做在线教育的,客户的定制化需求,要求同一个账号同时只能观看一个视频。(BS) 分析: 刚开始想过监听浏览器的close()事件,打开视频向redis 中存一个status,关闭浏览器修改这个status。但是不能处理极端情况如: 强制杀死进程、断电等(不考虑缓存播放视频的情况) 方案: 想到socket,自然想到netty对socket 的支持非常好。 为什么选择netty? API使用简单,开发门槛低 功能强大,预置了多种编解码器功能 几行代码,就能解决粘包\拆包问题 成熟、稳定

小驴 1016

unity制作交互视频/互动视频

unity制作交互视频/互动视频 思路 1.先让unity播放视频 2. 视频播放结束后,视频暂停,按钮出现 3.按钮跳转下一个视频 视频播放 先创建UI-Raw Iamge 在Raw Iamge 挂载组件 Video Player 接着挂载视频播放的脚本 using UnityEngine; using UnityEngine.UI; using UnityEngine.Video; publi...

weixin_45588911的博客 8423

Netty之通信协议和私有协议栈开发(三) 之 WebSocket协议开发

2021SC@SDUSC

May121812345的博客 2235

Linux -- 图形界面配置Samba;system-config-samba工具

图形界面配置Samba6.6.1 system-config-sambasystem-config-samba是Red Hat公司专门为Samba服务器管理编写的图形界面的管理工具,通过system-config-samba几乎可以完成对Samba服务器的所有配置,所以在只希望通过Samba服务器实现一些简单的资源共享时,system-config-samba是一个不错的选...

weixin_33695450的博客 2200

用Python实现一个猜密码的程序

我们用Python实现猜密码

sk6584631_sz的博客 1260

Netty权威指南——WebSocket协议开发

1.Http协议的弊端 半双工传输 消息格式造成的消息冗长繁复 可能造成对服务器的长时间轮询攻击等黑客攻击 2.WebSocket入门 WebSocket是HTML5开始提供的一种全双工的网络通讯协议,WebSocket基于TCP协议进行双向全双工消息传输,通讯双方只需要进行一个握手,然后就形成了一个快速通道,两者就可以持续通讯。相对于HTTP协议来说,通讯性能得到了很大的提升。 特点: 单一tcp连接,全双工通讯模式 对代理、防火墙、路由器透明 无头部、cookie和身份验证 无安全开销 通过“pi

weixin_42574365的博客 320

Android 13 系统定制:实现第三方Launcher预置与原生Launcher3的共存切换

本文详细介绍了在Android 13系统中实现第三方Launcher预置与原生Launcher3共存切换的技术方案。通过修改ResolverActivity逻辑、处理首次启动设置以及优化用户切换机制,开发者可以灵活定制默认Launcher,同时保留用户自由选择权。文章还提供了常见问题排查指南和性能优化建议,帮助提升双Launcher方案的稳定性和用户体验。

weixin_30275415的博客 126

netty实现WebSocket协议

文章目录WebSocket协议服务端开发客户端运行测试全双工 WebSocket协议 一般web应用都是使用的HTTP协议。HTTP协议有以下特点: 支持客户端-服务端模式 使用简单:只需要知道服务端URL,携带参数发送请求即可 支持多种传输数据类型,由消息头中content-type标识 无状态,使得HTTP服务轻量级 HTTP协议也存在一些缺点: 半双工通信:同一时刻,数据只能往同一方向...

刘本龙的专栏 3110

字节跳动已上岸测试工程师的面试经验

这个时候发面经已经有点晚了,所以现在打算让这篇面经主要面向即将秋招的童鞋,当然现在还在春招的童鞋也可以看哈,我和大家一起聊聊关于测试的二三事。   一、测试工程师的工作是什么?   测试工程师简单点说就是找bug,然后反馈给开发人员,不要小看这个工作。   首先很明显的bug开发人员有时候自己就能找到,测试人员要有比开发人员更加全面的想法才能找到深层次的问题点,   其次,要端正一个态度就是测试人员不是一个电脑小白,相反国外顶级的测试开发工程师同时也是顶级的开发工程师甚至更厉害,所以作为一个测试工程师一定要

m0_60745607的博客 2933

linux内核学习(八)---摄像头框架移植(上)

本章来开始进行摄像头的移植,同时回顾一下V4L2的整个框架

文艺小少年的博客 113

Netty-6 Http协议支持-websocket

一、websockt简介 一直以来,网络都是围绕着http协议进行开发的。然而,http会有一些固有的问题,所以websocket被引入。 (一)http缺点

mail_liuxing的专栏 537

想在 Visual Studio Code 里进行 ABAP 开发,需要安装的扩展列表

安装完毕后,我们可以将 SAP 系统配置为 Visual Studio Code 连接的远程文件系统。为了连接到 SAP 系统,需要启用 ABAP 开发工具 (ADT) ICF 节点,这与 SAP Hana Studio 等工具使用的服务相同。打开 SAP GUI 并连接到目标系统,运行事务 SICF,然后激活 ADT_SRV 服务,如下所示。这启用了允许代码编辑器和 IDE 连接到 SAP 系统的服务。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 3118

如何来实现IM?~webScoket 服务端开发

IM项目 脚手架搭建,由于最近的开发任务都是一些关于通过 fegin 或者httpClient 调用第三方接口的任务,其中遇到了一些数据实时性传输的问题,由于这方面的开发经验比较少,于是花了点时间来研究市面上主流的 scoket 技术,这也是我为什么写下本文的原因

风团团 1819

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

源码时代JAVA干货分享|带你用Netty框架实现WebSocket通信

功能介绍 Netty开发服务端 HTML实现客户端 实现服务端与客户端时实时交互 开发步骤 1.导包 <dependency> <groupId>io.netty</groupId> <artifactId>netty‐all</artifactId> <version>5.0.0.Alpha2</vers...

ITsource 419

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Netty——群聊系统与心跳机制与WebSocket开发

JAVA后端开发知识总结(持续更新…) Netty—— 文章目录Netty——一、Netty核心组件1.1 Bootstrap 和 ServerBootstrap1.2 Future 和 ChannelFuture1.3 Channel1.4 Selector1.5 ChannelHandler及其实现类1.6 Pipeline 和 ChannelPipeline二、EventLoop组件2.1 ChannelHandlerContext2.2 ChannelOption2.3 EventLoopGr.

weixin_43415481的博客 569

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

基于Netty5.0高级案例一之NettyWebsocket

前言介绍:     本案例主要介绍如何使用Netty开发websocket。 环境需求:     1、jdk1.7     2、Eclipse     3、Netty5.0     4、支持websocket的浏览器[火狐] 工程截图: 代码部分: 服务端: Global.java package c

每天积累一点,一年后你会发现,自己变化很大 677

netty+websocket实现心跳和断线重连

netty+websocket实现心跳和断线重连 去发现同类优质开源项目:https://gitcode.com/ 本资源文件提供了一个使用netty作为服务端实现websocket连接,并进行心跳检测和断线重连的示例。以下是该示例的具体介绍: 资源描述 本示例中,netty作为服务端,在websocket连接成功后,将channel保存到map集合中。客户端通过JavaScript发送心跳信息,...

gitblog_06704的博客 882

netty学习笔记(三)实现图文直播

文章目录前言图文直播上代码服务端客户端github 前言   在前面两篇,已经介绍了netty基础以及相关实践,今天我们来看下我大学期间完成的netty图文直播功能,当然其中也不乏在网上抄抄改改,这叫借鉴~ 图文直播   很久之前使用socket来实现,当然很多公司也是在用这个去实现客服系统。今天我们搞点netty 778. 上代码 服务端 1.配置相关配置,以及启动 2.我们来看下childH......

大鸡腿的博客 1862

十.Netty入门到超神系列-基于WebSocket开发聊天室

前言 在很多的网站中都嵌入有聊天功能,最理想的方式就是使用WebSocket来开发,屏幕面前的你如果不清楚WebSocket的作用可以自己去百度一下,Netty提供了WebSocket支持,这篇文章将使用Netty作为服务器,使用WebSocket开发一个简易的聊天室系统。 服务端 Netty提供了 WebSocketServerProtocolHandler ,它能够把平台的Http协议升级为WebSocket的WS协议,服务端代码如下 public class NettySocketServer {

墨家巨子@俏如来 3120

Netty Websocket使用

Netty Websocket协议开发 Netty基于HTTP协议栈开发了WebSocket协议栈,利用Netty的WebSocket协议栈可以方便开发WebSocket客户端和服务端 Netty Websocket服务端 1Netty Websocket服务端启动类 package com.webSocket; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; im...

CentOS 333
上一篇: socket.io服务端分析
下一篇: netty中的一个小bug
fjs_cloud
博客等级 码龄15年 248粉丝 192原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值