我们了解下,如何从HTTP切换到WebSocket,如何检测客户端是否支持WebSocket协议
我们先考虑创建一个基于WebSocket的实时聊天应用程序来演示下
该聊天应用程序的逻辑如下:
客户端发送一个消息
该消息被广播到其他链接的客户端
任何的人都可以和其他的人进行聊天,现在的客户端基本为网页端,我们专注于实现服务器端即可
如果HTTP请求指向了/ws的URI,那么HTTPRequestHandler将会调用FullHttpRequest对象上的retain()方法,并且转发给下一个InboundHandler,
如果不需要加密或者压缩,可以通过index.html进行零拷贝的使用
将index写入完成后,我们写入一个LastHttpContent标记响应的结束,如果不标注为keep-alive
还会添加一个CahnnelFutureListener到最后一次写出动作的ChannelFuture
然后调用writeAndFlush()
那么上面是简单的HTTP和webSocket协议变更的流程
对于WebSocket帧
我们说过有这着不同类型的WebSocketFrame,常见的有6种
我们的聊天记录将会使用如下的几种
CloseWebSocketFrame
PingWebSocketFrame
PongWebSocketFrame
TextWebSocketFrame
首先是TextWebScoketFrame处理的Handler
代码如下
然后是一个事件触发的机制
上面是一个事件处理,判断是否是握手成功了,如果成功了,就将这个Piepline中移除HttpRequestHandler
上面的处理器责任是在新的客户端的WebSocket握手完成后,将通知消息写到ChannelGroup中所有的Channel来通知已经连接的客户端,并且将这个Channel加入到ChannelGroup中
对应的引导类的代码如下
上面启动器类中的ChannelPipeline,其中包含的Handler如下
分别由编码器 聚合器已经自定义的处理器构成
WebSocketServerProtocolHandler会在握手完成之后,将所需的ChannelHandler添加上去,移除不需要的ChannelHandler
在握手之后
我们会将HttpRequestDecoder替换为WebSocketFrameDecoder
将HttpResponseEncoder替换为WebSocketFrameEncoder
并且会根据浏览器支持的版本,选择合适的
WebSocketFrameDecoder和WebSocketFrameEncoder
然后,对应的启动类如下