使用netty建立websocket進行群聊
阿新 • • 發佈:2019-02-07
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);
}