原文: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 參數。
三、自定義處理器握手後和文本消息