6、netty第五个例子,使用websocket来通讯
websocket中,可以支持双向的数据通信。其中所有的数据格式,都是以帧的形式来传递。
initializer
1 import io.netty.channel.ChannelInitializer; 2 import io.netty.channel.ChannelPipeline; 3 import io.netty.channel.socket.SocketChannel; 4 import io.netty.handler.codec.http.HttpObjectAggregator; 5 import io.netty.handler.codec.http.HttpServerCodec; 6 import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; 7 import io.netty.handler.stream.ChunkedWriteHandler; 8 9 public class WebSocketChannelinitializer extends ChannelInitializer<SocketChannel> { 10 11 @Override 12 protected void initChannel(SocketChannel ch) throws Exception { 13 ChannelPipeline pipeline = ch.pipeline(); 14 15 pipeline.addLast(new HttpServerCodec()); 16 pipeline.addLast(new ChunkedWriteHandler());//分块的方式 17 pipeline.addLast(new HttpObjectAggregator(8192));//http聚合 将块聚合成完整的 18 pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));//专门的websocket处理器, ws是指访问的路径 19 20 pipeline.addLast(new TextWebSocketFrameHandler()); 21 22 } 23 24 }
handler
1 import io.netty.channel.Channel; 2 import io.netty.channel.ChannelHandlerContext; 3 import io.netty.channel.SimpleChannelInboundHandler; 4 import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; 5 6 import java.time.LocalDateTime; 7 8 /** 9 * @ClassName: TextWebSocketFrameHandler websocket 都是以帧的形式来传递的,这里用的是文本 10 * @Description: 描述 11 * @Author: 12 * @CreateDate: 2019/9/1 17:08 13 * @Version: 1.0 14 */ 15 public class TextWebSocketFrameHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> { 16 17 @Override 18 protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception { 19 System.out.println("收到消息: " + msg.text()); 20 Channel channel = ctx.channel(); 21 channel.writeAndFlush(new TextWebSocketFrame("服务器时间: " + LocalDateTime.now())); 22 } 23 24 @Override 25 public void handlerAdded(ChannelHandlerContext ctx) throws Exception { 26 System.out.println("handlerAdded: " + ctx.channel().id().asLongText());//每个channel都有全局的id 分为长和短的 长的,保证唯一 短的不一定唯一 27 } 28 29 @Override 30 public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { 31 System.out.println("handlerRemoved: " + ctx.channel().id().asLongText()); 32 } 33 34 @Override 35 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 36 System.out.println("异常发生"); 37 ctx.close(); 38 } 39 }
页面例子:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>WebSocket客户端</title> 6 </head> 7 <body> 8 <!--第五个例子用到--> 9 <form onsubmit="return false;"> 10 <textarea name="message" style="width: 400px;height: 200px"> 11 </textarea> 12 13 <input type="button" value="发送短信" onclick="send(this.form.message.value)"> 14 15 <h3>服务器端输出:</h3> 16 17 <textarea id="responseText" style="width: 400px; height: 300px"> 18 19 </textarea> 20 21 <input type="button" onclick="javascript: document.getElementById('responseText').value = ''" value="清空内容"> 22 </form> 23 24 <script type="application/javascript"> 25 var socket; 26 if(window.WebSocket) { 27 socket = new WebSocket("ws://localhost:8899/ws"); 28 29 socket.onmessage = function (ev) { 30 //客户端获取到服务器端的消息 31 var ta = document.getElementById("responseText"); 32 ta.value = ta.value + "\n" + ev.data; 33 } 34 35 socket.onopen = function (ev) { 36 var ta = document.getElementById("responseText"); 37 ta.value = "连接开启"; 38 } 39 socket.onclose = function (ev) { 40 var ta = document.getElementById("responseText"); 41 ta.value = ta.value + "\n" + "连接关闭"; 42 } 43 44 } else { 45 alert("浏览器不支持WebSocket"); 46 } 47 48 function send(message) { 49 if(!window.WebSocket) { 50 return; 51 } 52 53 if(socket.readyState == WebSocket.OPEN) { 54 socket.send(message); 55 } else { 56 alert("连接未开启"); 57 } 58 } 59 </script> 60 61 </body> 62 </html>