南昌市物联网技防平台-后台
zengh
2021-03-23 ba0f00cf00c2a5c693e9608a56d1f7d032f5e216
blade-service/blade-jfpts/src/main/java/org/springblade/jfpt/webscoket/WebSocketHandler.java
New file
@@ -0,0 +1,161 @@
package org.springblade.jfpt.webscoket;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;
import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker;
import io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory;
import io.netty.util.CharsetUtil;
import java.util.Date;
import org.springblade.jfpt.suser.service.ISuserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class WebSocketHandler extends SimpleChannelInboundHandler<Object> {
   private WebSocketServerHandshaker handshaker;
   private  String on=null;
   @Autowired
   private  ISuserService suserService;
   private static WebSocketHandler webSocketHandler;
   @PostConstruct
   public void init() {
      webSocketHandler = this;
   }
   @Override
   protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
      if (msg instanceof FullHttpRequest) {
         //以http请求形式接入,但是走的是websocket
         handleHttpRequest(ctx, (FullHttpRequest) msg);
      } else if (msg instanceof WebSocketFrame) {
         //处理websocket客户端的消息
         handlerWebSocketFrame(ctx, (WebSocketFrame) msg);
      }
   }
   @Override
   public void channelActive(ChannelHandlerContext ctx) throws Exception {
      //添加连接
      System.out.println("客户端加入连接:" + ctx.channel());
      //ChannelSupervise.addChannel(ctx.channel());
   }
   @Override
   public void channelInactive(ChannelHandlerContext ctx) throws Exception {
      //断开连接
      System.out.println("客户端断开连接:" + ctx.channel());
      //用户离线状态
      String name = ChannelSupervise.findName(ctx.channel().id().asShortText());
      String num="0";
      webSocketHandler.suserService.updateUser(num,name);
      ChannelSupervise.removeChannel(ctx.channel());
   }
   @Override
   public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
      ctx.flush();
   }
   private void handlerWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) throws NumberFormatException, Exception {
      // 判断是否关闭链路的指令
      if (frame instanceof CloseWebSocketFrame) {
         handshaker.close(ctx.channel(), (CloseWebSocketFrame) frame.retain());
         return;
      }
      // 判断是否ping消息
      if (frame instanceof PingWebSocketFrame) {
         ctx.channel().write(
            new PongWebSocketFrame(frame.content().retain()));
         return;
      }
      // 本例程仅支持文本消息,不支持二进制消息
      if (!(frame instanceof TextWebSocketFrame)) {
         System.out.println("本例程仅支持文本消息,不支持二进制消息");
         throw new UnsupportedOperationException(String.format(
            "%s frame types not supported", frame.getClass().getName()));
      }
      // 返回应答消息
      String request = ((TextWebSocketFrame) frame).text();
      //把用户信息添加到通道里
      ChannelSupervise.addChannel(ctx.channel(),request);
      //用户在线状态
      this.on=request;
      String num="1";
      webSocketHandler.suserService.updateUser(num,request);
      TextWebSocketFrame tws = new TextWebSocketFrame(new Date().toString()
         + ctx.channel().id() + ":" + ctx.channel());
      // 返回【谁发的发给谁】
      ctx.channel().writeAndFlush(tws);
      // 群发
      //  ChannelSupervise.send2All(tws);
   }
   /**
    * 唯一的一次http请求,用于创建websocket
    *
    * @throws InterruptedException
    */
   private void handleHttpRequest(final ChannelHandlerContext ctx,
                           FullHttpRequest req) throws InterruptedException {
      //要求Upgrade为websocket,过滤掉get/Post
      if (!req.decoderResult().isSuccess() || (!"websocket".equals(req.headers().get("Upgrade")))) {
         //若不是websocket方式,则创建BAD_REQUEST的req,返回给客户端
         sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST));
         return;
      }
      //握手
      WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
         "ws://localhost:9034/websocket", null, false);
      handshaker = wsFactory.newHandshaker(req);
      if (handshaker == null) {
         WebSocketServerHandshakerFactory
            .sendUnsupportedVersionResponse(ctx.channel());
      } else {
         handshaker.handshake(ctx.channel(), req);
      }
   }
   /**
    * 拒绝不合法的请求,并返回错误信息
    */
   private static void sendHttpResponse(ChannelHandlerContext ctx,
                               FullHttpRequest req, DefaultFullHttpResponse res) {
      // 返回应答给客户端
      if (res.status().code() != 200) {
         ByteBuf buf = Unpooled.copiedBuffer(res.status().toString(),
            CharsetUtil.UTF_8);
         res.content().writeBytes(buf);
         buf.release();
      }
      ChannelFuture f = ctx.channel().writeAndFlush(res);
      // 如果是非Keep-Alive,关闭连接
//      if (!isKeepAlive(req) || res.status().code() != 200) {
//         f.addListener(ChannelFutureListener.CLOSE);
//      }
   }
   @Override
   public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
      cause.printStackTrace();
      ctx.close();
   }
}