2021SC@SDUSC

Netty 通过 WebSocket 编程实现服务器和客户端全双工长连接

实例要求:

  1. Http 协议是无状态的, 浏览器和服务器间的请求响应一次,下一次会重新创建连接.

  2. 要求:实现基于 webSocket 的长连接的全双工的交互

  3. 改变 Http 协议多次请求的约束,实现长连接了, 服务器可以发送消息给浏览器

  4. 客户端浏览器和服务器端会相互感知,比如服务器关闭了,浏览器会感知,同样浏览器关闭了,服务器会感知

  5. 运行界面

MyServer

package com.shandonguniversity.netty.websocket;import com.atguigu.netty.heartbeat.MyServerHandler;
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;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;import java.util.concurrent.TimeUnit;public class MyServer {public static void main(String[] args) throws Exception{//创建两个线程组EventLoopGroup bossGroup = new NioEventLoopGroup(1);EventLoopGroup workerGroup = new NioEventLoopGroup(); //8个NioEventLooptry {ServerBootstrap serverBootstrap = new ServerBootstrap();serverBootstrap.group(bossGroup, workerGroup);serverBootstrap.channel(NioServerSocketChannel.class);serverBootstrap.handler(new LoggingHandler(LogLevel.INFO));serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();//因为基于http协议,使用http的编码和解码器pipeline.addLast(new HttpServerCodec());//是以块方式写,添加ChunkedWriteHandler处理器pipeline.addLast(new ChunkedWriteHandler());/*说明1. http数据在传输过程中是分段, HttpObjectAggregator ,就是可以将多个段聚合2. 这就就是为什么,当浏览器发送大量数据时,就会发出多次http请求*/pipeline.addLast(new HttpObjectAggregator(8192));/*说明1. 对应websocket ,它的数据是以 帧(frame) 形式传递2. 可以看到WebSocketFrame 下面有六个子类3. 浏览器请求时 ws://localhost:7000/hello 表示请求的url4. WebSocketServerProtocolHandler 核心功能是将 http协议升级为 ws协议 (WebSocket), 保持长连接5. 是通过一个 状态码 101*/pipeline.addLast(new WebSocketServerProtocolHandler("/hello"));//hello请求地址有对应关系//自定义的handler ,处理业务逻辑pipeline.addLast(new MyTextWebSocketFrameHandler());}});//启动服务器ChannelFuture channelFuture = serverBootstrap.bind(7000).sync();channelFuture.channel().closeFuture().sync();}finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}
}

MyTextWebSocketFrameHandler

package com.shandonguniversity.netty.websocket;import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;import java.time.LocalDateTime;//这里 TextWebSocketFrame 类型,表示一个文本帧(frame),泛型
public class MyTextWebSocketFrameHandler extends SimpleChannelInboundHandler<TextWebSocketFrame>{@Overrideprotected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {//注意:以TextWebSocketFrame形式进行交互,如果改成String类型,信息就拿不到了System.out.println("服务器收到消息 " + msg.text());//回复消息ctx.channel().writeAndFlush(new TextWebSocketFrame("服务器时间" + LocalDateTime.now() + " " + msg.text()));}//当web客户端连接后, 触发方法@Overridepublic void handlerAdded(ChannelHandlerContext ctx) throws Exception {//id 表示唯一的值,LongText 是唯一的 ShortText 不是唯一System.out.println("handlerAdded 被调用" + ctx.channel().id().asLongText());System.out.println("handlerAdded 被调用" + ctx.channel().id().asShortText());}@Overridepublic void handlerRemoved(ChannelHandlerContext ctx) throws Exception {System.out.println("handlerRemoved 被调用" + ctx.channel().id().asLongText());}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {System.out.println("异常发生 " + cause.getMessage());ctx.close(); //关闭连接通道}
}

hello.html


<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<script>
//编写页面充当客户端功能var socket;//判断当前浏览器是否支持websocket编程if(window.WebSocket) {//支持websocket编程,go onsocket = new WebSocket("ws://localhost:7000/hello2");//相当于channelRead0, ev 收到服务器端回送的消息socket.onmessage = function (ev) {var rt = document.getElementById("responseText");rt.value = rt.value + "\n" + ev.data;//拼接}//相当于连接开启(感知到长连接开启)socket.onopen = function (ev) {var rt = document.getElementById("responseText");rt.value = "连接开启了.."}//相当于连接关闭(感知到长连接关闭)socket.onclose = function (ev) {var rt = document.getElementById("responseText");rt.value = rt.value + "\n" + "连接关闭了.."}} else {//不支持websocket编程alert("当前浏览器不支持websocket")}//发送消息到服务器function send(message) {if(!window.socket) { //先判断socket是否创建好return;}if(socket.readyState == WebSocket.OPEN) {//通过socket 发送消息,以TextWebSocketFrame形式进行交互,协议规定好的socket.send(message)} else {alert("连接没有开启");}}//onsubmit通过按钮触发相关时间
</script><form onsubmit="return false"><textarea name="message" style="height: 300px; width: 300px"></textarea><input type="button" value="发送消息" onclick="send(this.form.message.value)"><textarea id="responseText" style="height: 300px; width: 300px"></textarea><input type="button" value="清空内容" onclick="document.getElementById('responseText').value=''"></form>
</body>
</html>

运行截图

客户端浏览器


Eclipse服务器端


WebSocketServerProtocolHandler 核心功能是将 http协议升级为 ws协议 (WebSocket), 保持长连接, 是通过一个 状态码 101
如下图绿点处显示101 Switching Protacols,Response Headersz中upgrade:websocket

长连接,不会发一次就没有了。全双工,客户端浏览器和服务器可以两方面感知。

Netty 通过 WebSocket 编程实现服务器和客户端全双工长连接<2021SC@SDUSC>相关推荐

  1. Netty -Netty心跳检测机制案例,Netty通过WebSocket编程实现服务器和客户端长链接

    Netty心跳检测机制案例 案例要求 编写一个Netty心跳检测机制案例,当服务器超过3秒没有读时,就提示读空闲 当服务器超过5秒没有写操作时,提示写空闲 服务器超过7秒没有读或者写操作时,就提示读写 ...

  2. 【Linux】socket网络编程之服务器与客户端的数据交互

    [Linux]socket网络编程之服务器与客户端的数据交互 前言参考 argc !=2是什么意思 inet pton函数 对stdin,stdout 和STDOUT_FILENO,STDIN_FIL ...

  3. Java 服务器与客户端的简单连接

    今天刚学了一点socket,写了一个服务器与客户端的简单连接 利用的主要就是socket建立连接,发送数据 以下几个方法要注意: Socket(InetAddress  address, int  p ...

  4. 如何实现单服务器300万个长连接的?

    引自:http://www.zhihu.com/question/20831000 看到一篇文章说"最终我们采用了多消息循环.异步非阻塞的模型,在一台双核.24G内存的服务器上,实现峰值维持 ...

  5. ktor框架用到了netty吗_Ktor-构建异步服务器和客户端的 Kotlin 框架

    软件简介 Ktor 是一个使用 Kotlin 以最小的成本快速创建 Web 应用程序的框架. Ktor 是一个用于在连接系统(connected systems)中构建异步服务器和客户端的 Kotli ...

  6. Linux下TCP网络编程-创建服务器与客户端

    一.前言 互联网概念诞生于20世纪60年代末,从9几年中国接入互联网开始到现在,生活的每个角落都能看到网络的使用.现在物联网时代.共享经济的到来,生活中不仅仅电脑.手机可以接入网络,身边的各个设备也能 ...

  7. Qt网络编程——TCP服务器与客户端互发信息

    前言 前一个博客,试了TCP的服务器与客户端的连接与断开,接下就是客户端与服务器互发信息. 客户端 1.往服务器发送信息 //发送消息 void Client::on_buttonSendMessag ...

  8. [转]关于HTTP服务器每个客户端2个连接的限制

    这两天猫在家里搞一个多线程的断点续传得C#程序,发现同时只能开2个线程下载,其他的线程一律要等待,这样就导致下载大文件时其他线程经常超时,郁闷好久.今天回公司无意中发现了一个帖子,终于真相大白了,   ...

  9. 套接字的连接(服务器与客户端一对一的连接)

    套接字:是一种通信机制,通过这种机制,客户/服务器系统的开发工作既可以在本机可以络进行.                                   注:套接字的创建和使用与管道是有区别的,套 ...

最新文章

  1. C# JSON格式的字符串读取到类中
  2. html5游戏开发-零基础开发《圣诞老人送礼物》小游戏
  3. 【收藏】超全整理知识图谱相关学习资料,提供系统化的知识图谱学习路径
  4. linux5 iso镜像下载,Redhat Linux5.4/5.5/5.8/6.0/6.3 ISO镜像文件下载
  5. C语言实现电脑关机程序
  6. pdf转换器中文版下载
  7. node学习记三之vue与安装的模块(d3\echarts\jquery)
  8. Excel用户打死想不到:表格能做APP,WPS用户:金山系出品就是牛
  9. pyecharts画饼形图,圆形图,环形图(含百分比显示)【python干货】
  10. 检查xml格式是否正确
  11. 「解决方案」Acrel-2000Z变电站综合自动化系统
  12. sougou linux 无法切换中英文,Ubuntu 16.04安装GoLand后不能切换到搜狗输入法
  13. Daily record-October
  14. 技术分享 | EdgeX应用落地——零售、能源行业创新业务
  15. Ping通Tlenet不通,如何解决?
  16. 【体系结构】山东大学计算机体系结构知识点清单
  17. nslookup 入门命令详解
  18. Unity(三十七):3D模型动画、脚本控制模型骨骼IK动画
  19. Linux九阴真经之九阴白骨爪残卷7(Mariadb的三种安装方法)
  20. 7-5约分最简分式-python

热门文章

  1. Beetl开源那些事3
  2. 乡村爱情里的赵四;逗的大家笑尿裤子了
  3. 计算机毕业设计Java超市网站(源码+系统+mysql数据库+lw文档)
  4. 微人事(vhr)开源项目部署
  5. bose蓝牙音箱使用说明_性价比甄选 推荐这5款超值得入手的蓝牙音箱
  6. Skywalking+Nacos实现高可用集群和动态配置
  7. 在总账模块结账的时候提示总账和明细账对账不平结不了账
  8. 深度图+灰度图 可视化判断灰度图区域是否有深度
  9. halcon 计算图像的反余弦值:acos_image
  10. HDU 5730 Shell Necklace