原文:https://huan1993.iteye.com/blog/2433552

最近在学习netty相关的知识,看到netty可以实现 websoket,因此记录一下在netty中实现websocket的步骤,主要实现传递文本消息传递二进制消息,传递二进制消息由于需要传递额外信息,因此使用自定义消息协议。

需求:

1、使用 netty 实现 websocket 服务器

    2、实现 文本信息 的传递

    3、实现 二进制 信息的传递,如果是图片则传递到后台后在前台直接显示,非图片提示。(此处的图片和非图片是前端传递到后台的二进制数据然后后端在原封不动的直接返回到前台)

    4、只需要考虑 websocket 协议,不用处理http请求

实现细节:

1、netty中对websocket增强的处理器

WebSocketServerProtocolHandler 

>> 此处理器可以处理了 webSocket 协议的握手请求处理,以及 ClosePingPong控制帧的处理。对于文本和二进制的数据帧需要我们自己处理

>> 如果我们需要拦截 webSocket 协议握手完成后的处理,可以实现ChannelInboundHandler#userEventTriggered方法,并判断是否是 HandshakeComplete 事件。

>> 参数:websocketPath 表示 webSocket 的路径

>> 参数:maxFrameSize 表示最大的帧,如果上传大文件时需要将此值调大

2、文本消息的处理

客户端: 直接发送一个字符串即可

服务端: 服务端给客户端响应文本数据,需要返回  TextWebSocketFrame 对象,否则客户端接收不到。

3、二进制消息的处理

客户端:向后台传递一个 blob 对象即可,如果我们需要传递额外的信息,那么可以在 blob 对象中进行添加,此例中自定义前4个字节表示数据的类型。

服务端:处理 BinaryWebSocketFrame 帧,并获取前4个字节,判断是否是图片,然后返回 BinaryWebSocketFrame对象给前台。

4、针对二进制消息的自定义协议如下:(此处实现比较简单)

前四个字节表示文件类型,后面的字节表示具体的数据。

在java中一个int是4个字节,在js中使用Int32表示

此协议主要是判断前端是否传递的是 图片,如果是图片就直接传递到后台,然后后台在返回二进制数据到前台直接显示这个图片。非图片不用处理。

5、js中处理二进制数据

见 webSocket.html 文件中的处理。

实现步骤:

1、主要的依赖

  1. <dependency>
  2. <groupId>io.netty</groupId>
  3. <artifactId>netty-all</artifactId>
  4. <version>4.1.31.Final</version>
  5. </dependency>

2、webSocket服务端编写

  1. @Slf4j
  2. public class WebSocketServer {
  3. public static void main(String[] args) throws InterruptedException {
  4. EventLoopGroup bossGroup = new NioEventLoopGroup();
  5. EventLoopGroup workGroup = new NioEventLoopGroup();
  6. try {
  7. ServerBootstrap bootstrap = new ServerBootstrap();
  8. bootstrap.group(bossGroup, workGroup)
  9. .option(ChannelOption.SO_BACKLOG, 128)
  10. .childOption(ChannelOption.TCP_NODELAY, true)
  11. .childOption(ChannelOption.SO_KEEPALIVE, true)
  12. .handler(new LoggingHandler(LogLevel.TRACE))
  13. .channel(NioServerSocketChannel.class)
  14. .childHandler(new ChannelInitializer<SocketChannel>() {
  15. @Override
  16. protected void initChannel(SocketChannel ch) throws Exception {
  17. ch.pipeline()
  18. .addLast(new LoggingHandler(LogLevel.TRACE))
  19. // HttpRequestDecoder和HttpResponseEncoder的一个组合,针对http协议进行编解码
  20. .addLast(new HttpServerCodec())
  21. // 分块向客户端写数据,防止发送大文件时导致内存溢出, channel.write(new ChunkedFile(new File("bigFile.mkv")))
  22. .addLast(new ChunkedWriteHandler())
  23. // 将HttpMessage和HttpContents聚合到一个完成的 FullHttpRequest或FullHttpResponse中,具体是FullHttpRequest对象还是FullHttpResponse对象取决于是请求还是响应
  24. // 需要放到HttpServerCodec这个处理器后面
  25. .addLast(new HttpObjectAggregator(10240))
  26. // webSocket 数据压缩扩展,当添加这个的时候WebSocketServerProtocolHandler的第三个参数需要设置成true
  27. .addLast(new WebSocketServerCompressionHandler())
  28. // 服务器端向外暴露的 web socket 端点,当客户端传递比较大的对象时,maxFrameSize参数的值需要调大
  29. .addLast(new WebSocketServerProtocolHandler("/chat", null, true, 10485760))
  30. // 自定义处理器 - 处理 web socket 文本消息
  31. .addLast(new TextWebSocketHandler())
  32. // 自定义处理器 - 处理 web socket 二进制消息
  33. .addLast(new BinaryWebSocketFrameHandler());
  34. }
  35. });
  36. ChannelFuture channelFuture = bootstrap.bind(9898).sync();
  37. log.info("webSocket server listen on port : [{}]", 9898);
  38. channelFuture.channel().closeFuture().sync();
  39. } finally {
  40. bossGroup.shutdownGracefully();
  41. workGroup.shutdownGracefully();
  42. }
  43. }
  44. }

注意:

1、看一下上方依次引入了哪些处理器

2、对于 webSocket 的握手、Close、Ping、Pong等的处理,由 WebSocketServerProtocolHandler 已经处理了,我们自己只需要处理 Text和Binary等数据帧的处理。

3、对于传递比较大的文件,需要修改 maxFrameSize 参数。

3、自定义处理器握手后和文本消息

netty实现websocket发送文本和二进制数据的更多相关文章

  1. 【python】3.x,string与bytes的区别(文本,二进制数据)

    Python 3对文本和二进制数据作了更为清晰的区分.文本总是Unicode,由str类型表示, 二进制数据则由bytes类型表示. 不能拼接字符串和字节包,也无法在字节包里搜索字符串(反之亦然),也 ...

  2. 前端如何接收 websocket 发送过来的实时数据

    WebSocket protocol 是HTML5一种新的协议,它实现了浏览器与服务器全双工通信(full-duple).刚开始的握手需要借助HTTP请求完成,在 WebSocket API,浏览器和 ...

  3. 详细解读XMLHttpRequest(二)响应属性、二进制数据、监测上传下载进度

    本文主要参考:MDN 分析并操作 responseXML属性 如果你使用 XMLHttpRequest 来获得一个远程的 XML 文档的内容,responseXML 属性将会是一个由 XML 文档解析 ...

  4. IO流-文本IO\读写二进制数据

    文本IO 一.简述 OutputStreamWriter类使用选定的编码方式吧Unicode字符流转换为字节流,InputStreamReader类将包含字节的输入流转为可以产生Unicode字符的读 ...

  5. Asp.net Core中SignalR Core预览版的一些新特性前瞻,附源码(消息订阅与发送二进制数据)

    目录 SignalR系列目录(注意,是ASP.NET的目录.不是Core的) 前言 一晃一个月又过去了,上个月有个比较大的项目要验收上线.所以忙的脚不沾地.现在终于可以忙里偷闲,写一篇关于Signal ...

  6. 背水一战 Windows 10 (89) - 文件系统: 读写文本数据, 读写二进制数据, 读写流数据

    [源码下载] 背水一战 Windows 10 (89) - 文件系统: 读写文本数据, 读写二进制数据, 读写流数据 作者:webabcd 介绍背水一战 Windows 10 之 文件系统 读写文本数 ...

  7. Java模拟POST请求发送二进制数据

    在进行程序之间数据通信时我们有时候就需要自定义二进制格式,然后通过HTTP进行二进制数据交互.交互的示例代码如下: public static void main(String[] args) { S ...

  8. Hibernate 中 联合主键映射 组合关系映射 大对象映射(或者说文本大对象,二进制数据大对象)

    Clob:文本大对象,最长4G Blob:二进制数据大对象,最长4G util: public class HibUtil { private static SessionFactory sessio ...

  9. [ActionScript 3.0] AS利用ByteArray向PHP发送二进制数据生成图片

    flash as3向php发送二进制数据,通过php保存成图片. AS端: package { import com.JPEGEncoder.JPGEncoder; import flash.disp ...

随机推荐

  1. linux查看哪个进程占用磁盘IO

    方法一: $ iotop -oP 命令的含义:只显示有I/O行为的进程 测试结果: 方法二: $ pidstat -d 1 命令的含义:展示I/O统计,每秒更新一次 测试结果:

  2. Kubernetes 控制器之 Deployment 介绍(六)

    一.Deployment.ReplicaSet.Pod之间的关系 我们接着前面的文章说,如果不清楚的请查看之前的博文:http://blog.51cto.com/wzlinux/2322616 前面我 ...

  3. Legacy和UEFI,MBR和GPT的区别

    Legacy(历史的,遗留的,传统的)和UEFI指的是系统引导方式(Legacy为传统BIOS,UEFI为新式BIOS),MBR和GPT指的是磁盘分区表类型. 一般情况下都是Legacy+MBR, U ...

  4. ztree实现拖拽移动和复制

    1.官网下载ztree:http://www.treejs.cn/v3/api.php 2.引入jquery.ztree.all.min.js 注意,这是基于jQuery的插件,请引入相关js 3.设 ...

  5. Spring的日志管理

    一.spring的日志依赖 Logging是spring中唯一强制的外部依赖,spring中默认使用的日志是commons-logging,简称JCL,这里说的强制性,是因为在spring-core这 ...

  6. python实践项目五:操作剪贴板-pyperclip模块

    描述:读取剪贴板的内容,修改该内容,再将修改后的内容重新写进剪贴板 注意:执行程序代码前需保证剪贴板有内容,可复制以下内容来测试: Lists of animals Lists of aquarium ...

  7. 2019暑假牛客多校训练-第八场-C-CDMA(递归、水题)

    观察前3组可以推出递归规律,生成下一个类型时,每行copy自身与自身相反. 题目描述 Gromah and LZR have entered the third level. There is a b ...

  8. 腾讯明眸极速高清升级2.0,助力韩国赛事超高清5G直播

    近期,由腾讯云联合韩国CUDO通信研究所及intel推出的tile方式的viewport流服务编码,已正式通过测试.届时韩国最新5G网络将基于腾讯明眸-极速高清2.0和腾讯云直播产品能力,在韩国国内率 ...

  9. js 获取服务端时间,并实现时钟

    本例子以vue语法伪代码书写: 1,获取服务端北京时间 getRealTime() { let that = this; var xhr = new XMLHttpRequest(); if( !xh ...

  10. Selenium自动化获取WebSocket信息

    性能日志 ChromeDriver支持性能日志记录,您可以从中获取域“时间轴”,“网络”和“页面”的事件,以及指定跟踪类别的跟踪数据. 启用性能日志 默认情况下不启用性能日志记录.因此,在创建新会话时 ...