文章目录
WebSocket快速上手
1. WebSocket是什么?
WebSocket建立在TCP协议之上,并且与HTTP协议有着良好的兼容性,最大的特点就是服务器可以主动向客户端推送消息,客户端也可以主动向服务器发送消息。
1.1. WebSocket连接过程
- 客户端通过HTTP协议向服务端发送握手,服务端向客户端返回ACK,此时握手成功,建立连接并维持该连接;
- 后面服务端和客户端就可以基于建立的连接进行双向通信,直到连接关闭。
1.2. WebSocket与HTTP对比
HTTP | WebSocket | |
---|---|---|
通信方式 | 单工 | 全双工 |
端口 | 80/443 | 80/443 |
协议 | HTTP/HTTPS | WS/WSS |
跨域问题 | 有 | 无 |
网络开销 | - | 较小 |
1.3. WebSocket协议
WebSocket的协议标识符是 ws
,加密为 wss
,例如:
ws://ip:port/some/path
2. 快速上手
本次快速上手基于Netty实现。
2.1 服务端
WebSocketServer
主服务用于启动服务端,监听请求,并对请求信息进行解码,调用处理程序 WebSocketHandler
对请求进行处理。
public class WebSocketServer {
public void run() {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workGroup = new NioEventLoopGroup();
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 5).childOption(ChannelOption.SO_KEEPALIVE, true).childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel channel) throws Exception {
ChannelPipeline pipeline = channel.pipeline();
pipeline.addLast("http-codec", new HttpServerCodec());
pipeline.addLast("aggregator", new HttpObjectAggregator(65535));
pipeline.addLast("http-chunked", new ChunkedWriteHandler());
pipeline.addLast("handler", new WebSocketHandler());
}
});
try {
Channel channel = serverBootstrap.bind(8080).sync().channel();
channel.closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();
}
}
public static void main(String[] args) {
new WebSocketServer().run();
}
}
WebSocketHandler
作为请求处理器,主要接收并处理两种请求:
- 客户端握手请求
- 客户端消息请求,并给出响应。
public class WebSocketHandler extends ChannelInboundHandlerAdapter {
private WebSocketServerHandshaker handshaker;
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof FullHttpRequest) {
// websocket连接请求
handleHttpRequest(ctx, (FullHttpRequest) msg);
} else if (msg instanceof WebSocketFrame) {
// websocket业务处理
handleWebSocketRequest(ctx, (WebSocketFrame) msg);
}
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.close();
}
/**
* 获取WebSocket服务信息
*
* @param req
* @return
*/
private