public abstract class WebSocketServerHandshaker {
protected static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketServerHandshaker.class);
private static final ClosedChannelException CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace(
new ClosedChannelException(), WebSocketServerHandshaker.class, "handshake(...)");
private final String uri;
private final String[] subprotocols;
private final WebSocketVersion version;
private final int maxFramePayloadLength;
private String selectedSubprotocol;
public ChannelFuture handshake(Channel channel, FullHttpRequest req) {
return handshake(channel, req, null, channel.newPromise());
}
//握手过程
public final ChannelFuture handshake(Channel channel, FullHttpRequest req,
HttpHeaders responseHeaders, final ChannelPromise promise) {
//子类根据版本实现握手响应
FullHttpResponse response = newHandshakeResponse(req, responseHeaders);
//获取pipeline
ChannelPipeline p = channel.pipeline();
//ws握手完成后就当前channel就不需要处理htto请求了,所以需要移除http的handler
if (p.get(HttpObjectAggregator.class) != null) {
p.remove(HttpObjectAggregator.class);
}
if (p.get(HttpContentCompressor.class) != null) {
p.remove(HttpContentCompressor.class);
}
ChannelHandlerContext ctx = p.context(HttpRequestDecoder.class);
final String encoderName;
if (ctx == null) {
//实际会走这里
ctx = p.context(HttpServerCodec.class);
if (ctx == null) {
promise.setFailure(
new IllegalStateException("No HttpDecoder and no HttpServerCodec in the pipeline"));
return promise;
}
//加入ws解码器和编码器
p.addBefore(ctx.name(), "wsdecoder", newWebsocketDecoder());
p.addBefore(ctx.name(), "wsencoder", newWebSocketEncoder());
//记录HttpServerCodec的名字
encoderName = ctx.name();
} else {
p.replace(ctx.name(), "wsdecoder", newWebsocketDecoder());
encoderName = p.context(HttpResponseEncoder.class).name();
p.addBefore(encoderName, "wsencoder", newWebSocketEncoder());
}
//写入握手响应response
channel.writeAndFlush(response).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (future.isSuccess()) {
//成功后删除当前channel的HttpServerCodec编解码器
ChannelPipeline p = future.channel().pipeline();
p.remove(encoderName);
//设置成功状态
promise.setSuccess();
} else {
//设置失败状态
promise.setFailure(future.cause());
}
}
});
return promise;
}
//子类根据ws版本构建握手响应对象
protected abstract FullHttpResponse newHandshakeResponse(FullHttpRequest req,
HttpHeaders responseHeaders);
//子类根据ws版本创建解码器
protected abstract WebSocketFrameDecoder newWebsocketDecoder();
//子类根据ws版本创建编码器
protected abstract WebSocketFrameEncoder newWebSocketEncoder();
}
public class WebSocketServerHandshaker13 extends WebSocketServerHandshaker {
public static final String WEBSOCKET_13_ACCEPT_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
//是否允许扩展协议
private final boolean allowExtensions;
//是否允许缺失掩码
private final boolean allowMaskMismatch;
public WebSocketServerHandshaker13(
String webSocketURL, String subprotocols, boolean allowExtensions, int maxFramePayloadLength) {
this(webSocketURL, subprotocols, allowExtensions, maxFramePayloadLength, false);
}
public WebSocketServerHandshaker13(
String webSocketURL, String subprotocols, boolean allowExtensions, int maxFramePayloadLength,
boolean allowMaskMismatch) {
super(WebSocketVersion.V13, webSocketURL, subprotocols, maxFramePayloadLength);
this.allowExtensions = allowExtensions;
this.allowMaskMismatch = allowMaskMismatch;
}
@Override
protected FullHttpResponse newHandshakeResponse(FullHttpRequest req, HttpHeaders headers) {
//创建Respinse对象,设置响应状态101
FullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.SWITCHING_PROTOCOLS);
if (headers != null) {
res.headers().add(headers);
}
//Sec-WebSocket-Accept根据客户端请求首部的Sec-WebSocket-Key计算出来
//将Sec-WebSocket-Key跟258EAFA5-E914-47DA-95CA-C5AB0DC85B11拼接。
//通过SHA1计算出摘要,并转成base64字符串。
CharSequence key = req.headers().get(HttpHeaderNames.SEC_WEBSOCKET_KEY);
if (key == null) {
throw new WebSocketHandshakeException("not a WebSocket request: missing key");
}
String acceptSeed = key + WEBSOCKET_13_ACCEPT_GUID;
byte[] sha1 = WebSocketUtil.sha1(acceptSeed.getBytes(CharsetUtil.US_ASCII));
String accept = WebSocketUtil.base64(sha1);
//加入WS握手响应需要的HTTP头
res.headers().add(HttpHeaderNames.UPGRADE, HttpHeaderValues.WEBSOCKET);
res.headers().add(HttpHeaderNames.CONNECTION, HttpHeaderValues.UPGRADE);
res.headers().add(HttpHeaderNames.SEC_WEBSOCKET_ACCEPT, accept);
//选择服务器端支持的版本
String subprotocols = req.headers().get(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL);
if (subprotocols != null) {
String selectedSubprotocol = selectSubprotocol(subprotocols);
if (selectedSubprotocol == null) {
if (logger.isDebugEnabled()) {
logger.debug("Requested subprotocol(s) not supported: {}", subprotocols);
}
} else {
res.headers().add(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL, selectedSubprotocol);
}
}
return res;
}
//创建编码器
@Override
protected WebSocketFrameDecoder newWebsocketDecoder() {
return new WebSocket13FrameDecoder(true, allowExtensions, maxFramePayloadLength(), allowMaskMismatch);
}
//创建解码器
@Override
protected WebSocketFrameEncoder newWebSocketEncoder() {
return new WebSocket13FrameEncoder(false);
}
}
来源:https://blog.csdn.net/nimasike/article/details/99674455