1. 程式人生 > >使用netty建立websocket進行群聊

使用netty建立websocket進行群聊

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);


          }

程式碼地址