代码地址如下:
http://www.demodashi.com/demo/13577.html

一款基于Netty开发的WebSocket服务器

这是一款基于Netty框架开发的服务端,通信协议为WebSocket。主要用于Java后台服务器向浏览器进行消息推送。

需求

对于一个Web项目而言,客户端一般均为各种各样的浏览器,如何从后端服务器向浏览器客户端进行消息推送,便成了一个棘手的问题,好在在HTTP1.1之后,HTTP可以支持长连接,由此,我在Netty框架的基础上开发了这个WebSocket服务端。

当然,你依旧可以下载源码进行测试,集成,二次开发等等。

环境

  • Intellij IDEA2018
  • JDK 1.8
  • 插件:Simple WebSocket Client 0.1.3
    • FireFox Quantum 60.0.1 (64 位)
    • Google Chrome 67.0.3396.99(正式版本)(64 位)

运行结果

请看下图:

实现步骤及源码

WebSocket

WebSocket是HTML5开始提供的一种浏览器与服务器间进行全双工通讯的网络技术。 WebSocket通信协议于2011年被IETF定为标准RFC 6455,WebSocketAPI被W3C定为标准。 在WebSocket API中,浏览器和服务器只需要要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

目录结构

核心类讲解

  • WebSocketChildHandler
  • WebSocketServerHandler

WebSocketChildHandler

这个类的主要作用就是为Netty的通道注册事件。其核心代码见下,其中webSocketUrl就是客户端与服务端进行连接的请求路径,我将其写入了配置文件,交由Spring管理,以注入的方式传递到WebSocketServerHandler中。

  1. ChannelPipeline pipeline = socketChannel.pipeline();
  2. // 将请求与应答消息编码或者解码为HTTP消息
  3. pipeline.addLast("http-codec", new HttpServerCodec());
  4. // 将http消息的多个部分组合成一条完整的HTTP消息
  5. pipeline.addLast("aggregator", new HttpObjectAggregator(HttpObjectConstant.MAX_CONTENT_LENGTH));
  6. // 向客户端发送HTML5文件。主要用于支持浏览器和服务端进行WebSocket通信
  7. pipeline.addLast("http-chunked", new ChunkedWriteHandler());
  8. // 服务端Handler
  9. pipeline.addLast("handler", new WebSocketServerHandler(webSocketUrl));

WebSocketServerHandler

这个类是真正的核心类,这个类的主要功能为:

  • 进行第一次握手
  • 对消息进行处理
    • 可以实现点对点通信
    • 可以实现广播功能
    • 可以实现点对端通信
  1. /**
  2. * 接收客户端发送的消息
  3. *
  4. * @param channelHandlerContext ChannelHandlerContext
  5. * @param receiveMessage 消息
  6. */
  7. @Override
  8. protected void messageReceived(ChannelHandlerContext channelHandlerContext, Object receiveMessage) throws Exception {
  9. // 传统http接入 第一次需要使用http建立握手
  10. if (receiveMessage instanceof FullHttpRequest) {
  11. FullHttpRequest fullHttpRequest = (FullHttpRequest) receiveMessage;
  12. LOGGER.info("├ [握手]: {}", fullHttpRequest.uri());
  13. // 握手
  14. handlerHttpRequest(channelHandlerContext, fullHttpRequest);
  15. // 发送连接成功给客户端
  16. channelHandlerContext.channel().write(new TextWebSocketFrame("连接成功"));
  17. }
  18. // WebSocket接入
  19. else if (receiveMessage instanceof WebSocketFrame) {
  20. WebSocketFrame webSocketFrame = (WebSocketFrame) receiveMessage;
  21. handlerWebSocketFrame(channelHandlerContext, webSocketFrame);
  22. }
  23. }
  24. /**
  25. * 第一次握手
  26. *
  27. * @param channelHandlerContext channelHandlerContext
  28. * @param req 请求
  29. */
  30. private void handlerHttpRequest(ChannelHandlerContext channelHandlerContext, FullHttpRequest req) {
  31. // 构造握手响应返回,本机测试
  32. WebSocketServerHandshakerFactory wsFactory
  33. = new WebSocketServerHandshakerFactory(webSocketUrl, Constant.NULL, Constant.FALSE);
  34. // region 从连接路径中截取连接用户名
  35. String uri = req.uri();
  36. int i = uri.lastIndexOf("/");
  37. String userName = uri.substring(i + 1, uri.length());
  38. // endregion
  39. Channel connectChannel = channelHandlerContext.channel();
  40. // 加入在线用户
  41. WebSocketUsers.put(userName, connectChannel);
  42. socketServerHandShaker = wsFactory.newHandshaker(req);
  43. if (socketServerHandShaker == null) {
  44. // 发送版本错误
  45. WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(connectChannel);
  46. } else {
  47. // 握手响应
  48. socketServerHandShaker.handshake(connectChannel, req);
  49. }
  50. }
  51. /**
  52. * webSocket处理逻辑
  53. *
  54. * @param channelHandlerContext channelHandlerContext
  55. * @param frame webSocketFrame
  56. */
  57. private void handlerWebSocketFrame(ChannelHandlerContext channelHandlerContext, WebSocketFrame frame) throws IOException {
  58. Channel channel = channelHandlerContext.channel();
  59. // region 判断是否是关闭链路的指令
  60. if (frame instanceof CloseWebSocketFrame) {
  61. LOGGER.info("├ 关闭与客户端[{}]链接", channel.remoteAddress());
  62. socketServerHandShaker.close(channel, (CloseWebSocketFrame) frame.retain());
  63. return;
  64. }
  65. // endregion
  66. // region 判断是否是ping消息
  67. if (frame instanceof PingWebSocketFrame) {
  68. LOGGER.info("├ [Ping消息]");
  69. channel.write(new PongWebSocketFrame(frame.content().retain()));
  70. return;
  71. }
  72. // endregion
  73. // region 纯文本消息
  74. if (frame instanceof TextWebSocketFrame) {
  75. String text = ((TextWebSocketFrame) frame).text();
  76. LOGGER.info("├ [{} 接收到客户端的消息]: {}", new Date(), text);
  77. channel.write(new TextWebSocketFrame(new Date() + " 服务器将你发的消息原样返回:" + text));
  78. }
  79. // endregion
  80. // region 二进制消息 此处使用了MessagePack编解码方式
  81. if (frame instanceof BinaryWebSocketFrame) {
  82. BinaryWebSocketFrame binaryWebSocketFrame = (BinaryWebSocketFrame) frame;
  83. ByteBuf content = binaryWebSocketFrame.content();
  84. LOGGER.info("├ [二进制数据]:{}", content);
  85. final int length = content.readableBytes();
  86. final byte[] array = new byte[length];
  87. content.getBytes(content.readerIndex(), array, 0, length);
  88. MessagePack messagePack = new MessagePack();
  89. WebSocketMessageEntity webSocketMessageEntity = messagePack.read(array, WebSocketMessageEntity.class);
  90. LOGGER.info("├ [解码数据]: {}", webSocketMessageEntity);
  91. WebSocketUsers.sendMessageToUser(webSocketMessageEntity.getAcceptName(), webSocketMessageEntity.getContent());
  92. }
  93. // endregion
  94. }

至此,服务端算是开发完成。但可以看出,服务端中仍有很大的发展空间,细心的同学可以发现我在第一次握手时,将Channel存储了起来,对于上述的三种情况也有简易的实现方案。

如果有必要,我也会将非浏览器客户端代码(非Js客户端)写成例子,共享出来。

一款基于Netty开发的WebSocket服务器

代码地址如下:
http://www.demodashi.com/demo/13577.html

注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权

一款基于Netty开发的WebSocket服务器的更多相关文章

  1. (二)基于Netty的高性能Websocket服务器(netty-websocket-spring-boot)

    @toc Netty是一款基于NIO(Nonblocking I/O,非阻塞IO)开发的网络通信框架,对比于BIO(Blocking I/O,阻塞IO),他的并发性能得到了很大提高. 1.Netty为 ...

  2. Xsoup 是一款基于 Jsoup 开发的

    Xsoup 是一款基于Jsoup 开发的,使用XPath抽取Html元素的工具.它被用于作者的爬虫框架 WebMagic 中,进行XPath 解析和抽取. 此次更新主要增加了一些XPath语法的支持. ...

  3. 基于线程开发一个FTP服务器

    一,项目题目:基于线程开发一个FTP服务器 二,项目要求: 基本要求: 1.用户加密认证   2.允许同时多用户登录   3.每个用户有自己的家目录 ,且只能访问自己的家目录   4.对用户进行磁盘配 ...

  4. easy-im:一款基于netty的即时通讯系统

    介绍 easy-im是面向开发者的一款轻量级.开箱即用的即时通讯系统,帮助开发者快速搭建消息推送等功能. 基于easy-im,你可以快速实现以下功能: + 聊天软件 + IoT消息推送 基本用法 项目 ...

  5. VBox 一款基于vue开发的音乐盒 序章

    己基于vue写了一个 Mplayer, github地址:https://github.com/xiangwenhu/MPlaer, 演示地址:http://babydairy2017.cloudap ...

  6. Netty实现简单WebSocket服务器

    本文参考<Netty权威指南>├── WebSocketServerHandler.java├── WebSocketServer.java└── wsclient.html packag ...

  7. 推荐一款基于 AI 开发的 IDE 插件,帮助提升编码效率

    最近在浏览技术社区的时候,发现了一款神奇 IDE 插件,官网称可以利用 AI 帮助程序员写代码,一下子吸引了我的好奇心.赶紧下载下来使用一番,感觉确实蛮神奇,可以火速提升编程效率. 这款插件叫做 ai ...

  8. 一款基于 Android 开发的离线版的 MM 图片浏览 App

    一款离线版的 MM 图片浏览 App,有点类似掌上百度的图片专栏应用.图片采用瀑布流展示方式,点击图片集,支持左右手势滑动切换图片:支持放大缩小功能. 实现功能:1)图片完全离线,不耗个人 GPRS ...

  9. 谈谈如何使用Netty开发实现高性能的RPC服务器

    RPC(Remote Procedure Call Protocol)远程过程调用协议,它是一种通过网络,从远程计算机程序上请求服务,而不必了解底层网络技术的协议.说的再直白一点,就是客户端在不必知道 ...

随机推荐

  1. [BZOJ2109][NOI2010]航空管制(贪心+拓扑)

    2109: [Noi2010]Plane 航空管制 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1227  Solved: 510[Submit][ ...

  2. hdu 1531 king(差分约束)

    King Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  3. 【找规律】【DFS】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem A. Arithmetic Derivative

    假设一个数有n个质因子a1,a2,..,an,那么n'=Σ(a1*a2*...*an)/ai. 打个表出来,发现一个数x,如果x'=Kx,那么x一定由K个“基础因子”组成. 这些基础因子是2^2,3^ ...

  4. 【置换群】poj3270 Cow Sorting

    并不应该叫置换群……只是用到了置换而已,并没有群. 题解看这个吧,我就不写了:http://www.cnblogs.com/kuangbin/archive/2012/09/03/2669013.ht ...

  5. Git 学习(一)简介及安装

    Git 简介及安装 Git是目前世界上最先进的分布式版本控制系统(没有之一).它的诞生也颇具传奇,Linux创始人Linus花了两周时间自己用C写了一个分布式版本控制系统,这就是Git!有兴趣的话,可 ...

  6. mybatis 执行传入的任意sql语句

    dao类 /** * 自定义sql查询 * @param sqlContent * @return */ public List<LinkedHashMap<String, Object& ...

  7. xpages开发的bom管理系统

    domino对流程设计是方便的.假设制作复杂逻辑的应用就难了.可是还是能够实现的,曾经的一个bom管理系统.刚開始想使用java的ssh来做,后来为了统一平台.还是使用domino来做,经过长时间的研 ...

  8. [转]How to handle Failed Rows in a Data Flow

    本文转自:http://www.rad.pasfu.com/index.php?/archives/23-How-to-handle-Failed-Rows-in-a-Data-Flow.html s ...

  9. unity macro 分平台处理

    https://docs.unity3d.com/ScriptReference/SystemInfo.html https://docs.unity3d.com/Manual/PlatformDep ...

  10. unity pbr

    https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf 参数