原文:https://huan1993.iteye.com/blog/2433552javascript
最近在学习netty相关的知识,看到netty能够实现 websoket,所以记录一下在netty中实现websocket的步骤,主要实现传递文本消息和传递二进制消息,传递二进制消息因为须要传递额外信息,所以使用自定义消息协议。html
需求:
一、使用 netty 实现 websocket 服务器前端
二、实现 文本信息 的传递java
三、实现 二进制 信息的传递,若是是图片则传递到后台后在前台直接显示,非图片提示。(此处的图片和非图片是前端传递到后台的二进制数据而后后端在原封不动的直接返回到前台)git
四、只须要考虑 websocket 协议,不用处理http请求web
实现细节:
一、netty中对websocket加强的处理器
WebSocketServerProtocolHandler bootstrap
>> 此处理器能够处理了 webSocket 协议的握手请求处理,以及 Close、Ping、Pong控制帧的处理。对于文本和二进制的数据帧须要咱们本身处理。后端
>> 若是咱们须要拦截 webSocket 协议握手完成后的处理,能够实现ChannelInboundHandler#userEventTriggered方法,并判断是不是 HandshakeComplete 事件。数组
>> 参数:websocketPath 表示 webSocket 的路径服务器
>> 参数:maxFrameSize 表示最大的帧,若是上传大文件时须要将此值调大
二、文本消息的处理
客户端: 直接发送一个字符串便可
服务端: 服务端给客户端响应文本数据,须要返回 TextWebSocketFrame 对象,不然客户端接收不到。
三、二进制消息的处理
客户端:向后台传递一个 blob 对象便可,若是咱们须要传递额外的信息,那么能够在 blob 对象中进行添加,此例中自定义前4个字节表示数据的类型。
服务端:处理 BinaryWebSocketFrame 帧,并获取前4个字节,判断是不是图片,而后返回 BinaryWebSocketFrame对象给前台。
四、针对二进制消息的自定义协议以下:(此处实现比较简单)
前四个字节表示文件类型,后面的字节表示具体的数据。
在java中一个int是4个字节,在js中使用Int32表示
此协议主要是判断前端是否传递的是 图片,若是是图片就直接传递到后台,而后后台在返回二进制数据到前台直接显示这个图片。非图片不用处理。
五、js中处理二进制数据
见 webSocket.html 文件中的处理。
实现步骤:
一、主要的依赖
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty-all</artifactId>
- <version>4.1.31.Final</version>
- </dependency>
二、webSocket服务端编写
- @Slf4j
- public class WebSocketServer {
-
- public static void main(String[] args) throws InterruptedException {
- EventLoopGroup bossGroup = new NioEventLoopGroup();
- EventLoopGroup workGroup = new NioEventLoopGroup();
- try {
- ServerBootstrap bootstrap = new ServerBootstrap();
- bootstrap.group(bossGroup, workGroup)
- .option(ChannelOption.SO_BACKLOG, 128)
- .childOption(ChannelOption.TCP_NODELAY, true)
- .childOption(ChannelOption.SO_KEEPALIVE, true)
- .handler(new LoggingHandler(LogLevel.TRACE))
- .channel(NioServerSocketChannel.class)
- .childHandler(new ChannelInitializer<SocketChannel>() {
- @Override
- protected void initChannel(SocketChannel ch) throws Exception {
- ch.pipeline()
- .addLast(new LoggingHandler(LogLevel.TRACE))
-
- .addLast(new HttpServerCodec())
-
- .addLast(new ChunkedWriteHandler())
-
-
- .addLast(new HttpObjectAggregator(10240))
-
- .addLast(new WebSocketServerCompressionHandler())
-
- .addLast(new WebSocketServerProtocolHandler("/chat", null, true, 10485760))
-
- .addLast(new TextWebSocketHandler())
-
- .addLast(new BinaryWebSocketFrameHandler());
- }
- });
- ChannelFuture channelFuture = bootstrap.bind(9898).sync();
- log.info("webSocket server listen on port : [{}]", 9898);
- channelFuture.channel().closeFuture().sync();
- } finally {
- bossGroup.shutdownGracefully();
- workGroup.shutdownGracefully();
- }
- }
- }
注意:
一、看一下上方依次引入了哪些处理器
二、对于 webSocket 的握手、Close、Ping、Pong等的处理,由 WebSocketServerProtocolHandler 已经处理了,咱们本身只须要处理 Text和Binary等数据帧的处理。
三、对于传递比较大的文件,须要修改 maxFrameSize 参数。
三、自定义处理器握手后和文本消息