原文: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. RedisTemplate通过scan方法进行自定义操作:1、根据hashKey的名称匹配相关hash键值对

    需求:有一个hash如下,现在想查询出stream前缀的键值对 操作方法如下: package com.example; import org.junit.Before; import org.jun ...

  2. 系统运维工程师装逼完全指南(转载Mark)

    1.全球化的认证有助于提升逼格,什么OCM.CCIE.RHCA.CISSP等等能考都考,再不济,也要有一张系统架构设计师或者网络规划设计师的信产部认证.每过一个认证,逼格提升一档. 2.TCP/IP协 ...

  3. LeetCode Top Interview Questions

    LeetCode Top Interview Questions https://leetcode.com/problemset/top-interview-questions/ # No. Titl ...

  4. POJ 1221 UNIMODAL PALINDROMIC DECOMPOSITIONS

    总时间限制: 1000ms 内存限制: 65536kB 描述 A sequence of positive integers is Palindromic if it reads the same f ...

  5. 【剑指offer】面试题 14. 剪绳子

    面试题 14. 剪绳子 LeetCode 题目描述 给你一根长度为 n 的绳子,请把绳子剪成 m 段(m.n 都是整数,n>1 并且 m>1),每段绳子的长度记为 k[0],k[1],·· ...

  6. 在 SQL 中 快速 批量 插入数据的方法

    方法1:逐条执行,速度慢. INSERT INTO testimport (name, message) VALUES ('testname', 'jfksdfkdsfjksadljfkdsfjsdl ...

  7. Java开发笔记(一百三十一)Swing的列表框

    前面介绍了选择框的用法,当时为了方便用户勾勾点点,无论是复选框还是单选按钮,统统把所有选项都摆在界面上.倘若只有两三个选项还好办,要是选项数量变多比如超过五个,这么多的选择框一齐在界面罗列,不光程序员 ...

  8. Java开发笔记(一百三十三)Swing的菜单

    传统的桌面程序基本是对某种类型的文件进行加工,例如Window自带的记事本用来读写文本文件,自带的画图程序用来查看和修改位图文件.为了方便用户切换各种操作,这些程序在窗口顶端放了一排菜单栏,单击菜单栏 ...

  9. 使用GIT上传文件,VSCODE使用GIT上传项目

    GIT使用方法: 1.安装git 2.设置用户名和邮箱: git config --global user.name="haokan1113" git config --globa ...

  10. flask框架(七)——蓝图、请求上下文、g对象、信号、flask_session

    蓝图 作用:对程序进行目录结构划分 不使用蓝图情况下,自己分文件 目录结构: -templates -views -__init__.py -user.py -order.py -app.py app ...