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

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

需求:

1、使用 netty 实现 websocket 服务器

    2、实现 文本信息 的传递

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

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

实现细节:

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

WebSocketServerProtocolHandler 

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

>> 如果我们需要拦截 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. Samba通过ad域进行认证并限制空间大小

    最近正在做单位电脑的AD域管理. 为漫游用户文件,研究配置Samba通过ad域进行认证并限制空间大小. 参考了很多资料,现总结如下: DC:windows server 2016(配置安装域控制器)略 ...

  2. 【linux基础err】NVIDIA-SMI has failed because it could't communicate with the NVIDIA driver.

    问题 安装nvidia driver和cuda关机重启之后出现不能进入系统的问题,进入命令行模式使用nvidia-smi检查驱动的问题. nvidia-smi NVIDIA-SMI has faile ...

  3. jQuery hashchange监听浏览器url变化

    $(window).bind('hashchange', function() { // });

  4. pip修改成国内镜像源

    临时指定镜像源 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple seaborn 永久修改镜像源 linux下,修改 ~/.pip/pip ...

  5. ubuntu18.04LTS服务器安装matlab4a

    下载matlab安装文件共包含三个文件:MATHWORKS_R2014A.part1.rar, MATHWORKS_R2014A.part2.rar, 相关文件(Crack)解压:$sudo apt ...

  6. C++中的强制类型转换

    在C语言中,强制类型转换的方式为(Type)Expression,另外还有一种现在已经不用的旧式写法Type(Expression),这两种方式是等价的. 但是,C语言的强制类型转换方式存在一些问题: ...

  7. 文件和异常——python从编程入门到实践

    从文件中读取数据 1. 读取整个文件 要读取文件,首先来创建一个文件: 然后打开并读取这个文件,再将其内容显示到屏幕上: file_reader.py with open('pi_digits.txt ...

  8. Django模型层之更多操作

    Django模型层之更多操作 一 .ORM字段 1.1 常用字段 AutoField int自增列,必须填入参数 primary_key=True.当model中如果没有自增列,则自动会创建一个列名为 ...

  9. kubernetes 实践四:Pod详解

    本篇是关于k8s的Pod,主要包括Pod和容器的使用.Pod的控制和调度管理.应用配置管理等内容. Pod的定义 Pod是k8s的核心概念一直,就名字一样,是k8s中一个逻辑概念.Pod是docekr ...

  10. Mybatis @Result注解的使用案例

    @Result注解的使用