WebSocket 简介:
WebSocket 规范定义了一种 API,可在网络浏览器和服务器之间建立“套接字”连接。简单地说:客户端和服务器之间存在持久的连接,而且双方都可以随时开始发送数据。
第一次请求客户端发送的是http请求,请求头中包含websocket相关的信息,服务器端对请求进行验证,所以要添加一些http 的解码编码handler,同时也要添加WebSocket 的handler处理器,如下:
public class ChildChannelHandler extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast("decoder", new HttpRequestDecoder()); //用于解析http报文的handler
ch.pipeline().addLast("aggregator", new HttpObjectAggregator(65536)); //用于将解析出来的数据封装成http对象,httprequest什么的
ch.pipeline().addLast("encoder", new HttpResponseEncoder()); //用于将response编码成httpresponse报文发送
ch.pipeline().addLast("handshake", new WebSocketServerProtocolHandler("", "", true)); //websocket的handler部分定义的,它会自己处理握手等操作
ch.pipeline().addLast("handler", new MyWebSocketServerHandler());
}
}
第一次处理的事http 请求,等到建立WebSocket 之后就需要处理WebSocket的请求,如下代码:
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof FullHttpRequest) {
handleHttpRequest(ctx, ((FullHttpRequest) msg));
} else if (msg instanceof WebSocketFrame) {
handlerWebSocketFrame(ctx, (WebSocketFrame) msg);
}
}
接下来告诉客户端,接下来的数据按照websocket协议来发送内容了,以及启动websocket服务器在制定的端口上
private void handleHttpRequest(ChannelHandlerContext ctx,
FullHttpRequest req) {
if (!req.getDecoderResult().isSuccess()
|| (!"websocket".equals(req.headers().get("Upgrade")))) {
sendHttpResponse(ctx, req, new DefaultFullHttpResponse(
HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST));
return;
}
WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
"ws://localhost:8888/websocket", null, false);
handshaker = wsFactory.newHandshaker(req);
if (handshaker == null) {
WebSocketServerHandshakerFactory
.sendUnsupportedVersionResponse(ctx.channel());
} else {
handshaker.handshake(ctx.channel(), req);
}
}
最后,在读取到消息时websocket类型过后,将消息进行群发
private void handlerWebSocketFrame(ChannelHandlerContext ctx,
WebSocketFrame frame) {
// 返回应答消息
String request = ((TextWebSocketFrame) frame).text();
System.out.println("recv:" + request);
TextWebSocketFrame tws = new TextWebSocketFrame(new Date().toString()
+ ctx.channel().localAddress() + ":" + request);
// 群发
MyChannelGroup.group.writeAndFlush(tws);
}