WebSocket
WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。
WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
实例
实例要求:
- Http协议是无状态的, 浏览器和服务器间的请求响应一次,下一次会重新创建连接.
- 要求:实现基于webSocket的长连接的全双工的交互
- 改变Http协议多次请求的约束,实现长连接了, 服务器可以主动发送消息给浏览器
- 客户端浏览器和服务器端会相互感知,比如服务器关闭了,浏览器会感知,同样浏览器关闭了,服务器会感知。
服务端

1 2 3 4 5 6 7 8 9 10 11 12 13 14
| pipeline.addLast(new HttpServerCodec());
pipeline.addLast(new ChunkedWriteHandler());
pipeline.addLast(new HttpObjectAggregator(8192));
pipeline.addLast(new WebSocketServerProtocolHandler("/hello"));
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| public class MyServer {
public static void main(String[] args) { NioEventLoopGroup bossGroup = new NioEventLoopGroup(1); NioEventLoopGroup workerGroup = new NioEventLoopGroup(8);
try { ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new ChannelInitializer<SocketChannel>() {
@Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new HttpServerCodec()); pipeline.addLast(new ChunkedWriteHandler()); pipeline.addLast(new HttpObjectAggregator(8192));
pipeline.addLast(new WebSocketServerProtocolHandler("/hello"));
pipeline.addLast(new MyTextWebSocketFrameHandler()); } });
ChannelFuture channelFuture = bootstrap.bind(7000).sync();
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) { e.printStackTrace(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } }
|
自定义处理器

以TextWebSocketFrame
文本桢的形式交互
channel的ID有两种形式
ctx.channel().id().asLongText()
唯一
ctx.channel().id().asShortText()
不唯一
客户端页面
HTML5 WebSocket:https://www.runoob.com/html/html5-websocket.html

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script> var socket; if(window.WebSocket) { socket = new WebSocket("ws://localhost:7000/hello"); socket.onmessage = function (ev) { var rt = document.getElementById("responseText"); rt.value = rt.value + "\n" + ev.data; }
socket.onopen = function (ev) { var rt = document.getElementById("responseText"); rt.value = "连接开启了.." }
socket.onclose = function (ev) {
var rt = document.getElementById("responseText"); rt.value = rt.value + "\n" + "连接关闭了.." } } else { alert("当前浏览器不支持websocket") }
function send(message) { if(!window.socket) { return; } if(socket.readyState == WebSocket.OPEN) { socket.send(message) } else { alert("连接没有开启"); } } </script> <form onsubmit="return false"> <textarea name="message" style="height: 300px; width: 300px"></textarea> <input type="button" value="发生消息" onclick="send(this.form.message.value)"> <textarea id="responseText" style="height: 300px; width: 300px"></textarea> <input type="button" value="清空内容" onclick="document.getElementById('responseText').value=''"> </form> </body> </html>
|
测试
启动服务器
访问页面

发送消息
)
服务器可以发送消息给浏览器
关闭页面,断开连接(这里服务器我重启了ID所以不一样)。

关闭服务器

客户端浏览器和服务器端会相互感知,比如服务器关闭了,浏览器会感知,同样浏览器关闭了,服务器会感知。
细节
WebSocket服务器通过101
状态码切换协议由http->ws。
