为祖国建设添砖java 2023-06-01 02:16 采纳率: 66.7%
浏览 35
已结题

websocket无法同时建立很多连接问题

佬们,我现在想要做一个硬件监控系统,前端是微信小程序。首先使用mqtt协议将硬件与java后端通信,这步实现了。因为监控系统嘛,后端一收到硬件信息就主动推送给前端该设备的所有者。想到使用websocket实现后端主动推送信息,但是会有很多用户同时在小程序查看设备,没办法建立这么多websocket连接怎么办呢

  • 写回答

2条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2023-06-01 04:02
    关注
    • 这篇博客: 【开源物联网】基于WebSocket进行MQTT通信中的 2.2建立WebSocket连接 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
    • 以微信小程序作为客户端,建立与服务端简的WebSocket连接,客户端操作详情请参考微信小程序MQTT通信及开源框架实现,本文关注基于WebSocket进行MQTT的流程。

      建立WebSocket连接由两个步骤完成:

      •  客户端首先通过http协议发送一条协议升级(升级到websocket)请求报文;
      • 服务端进行握手成功后返回一条101 http协议报文表示WebSocket连接已建立。

      其代码实现如下:

      /**
      	 * 唯一的一次http请求,用于创建websocket
      	 */
      	private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) {
      		// 要求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;
      		}
      		logger.info(req.content());
      		// ctx.fireChannelRead(req.content());
      		WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
      				"ws://localhost:1885/websocket",
      				"mqtt", false);
      		handshaker = wsFactory.newHandshaker(req);
      		if (handshaker == null) {
      			WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());
      		} else {
      			req.headers().set("Sec-WebSocket-Protocol", "mqtt");
      			handshaker.handshake(ctx.channel(), req);
      		}
      	}

       识别出收到的报文是Http报文时在第22行进行握手完成协议升级成websocket协议建立连接。

      建立连接过程跟踪

      采用wireshark工具对连接过程进行跟踪可以看到如下报文信息:

      WebSocket连接建立报文跟踪 

      从服务器端返回的101报文表示建立连接成功。

    • 以下回答由chatgpt基于相关博客总结生成:

      可以考虑使用WebSocket的广播机制来优化这个问题,避免建立多个WebSocket连接。具体实现方法如下:

      1.在后端建立一个WebSocket连接,并且保存下来。 2.使用一个数据结构来保存所有需要推送的消息,这个数据结构可以使用队列、堆栈等等,根据实际需求选择。 3.当有需要推送的消息时,将消息加入数据结构中。 4.使用WebSocket的广播机制,将数据结构中的消息发送给所有客户端; 5.客户端收到消息后,将其展示在界面上。

      具体的实现细节可以参考以下代码示例:

      后端代码示例:

      // 建立WebSocket连接 private void initWebSocket() { // 创建一个WebSocketServerHandshakerFactory对象 WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory( "ws://localhost:8888/websocket", null, false);

      // 通过WebSocketServerHandshakerFactory对象创建一个WebSocketServerHandshaker对象
      handshaker = wsFactory.newHandshaker(request);
      if (handshaker == null) {
          WebSocketServerHandshakerFactory.sendUnsupportedWebSocketVersionResponse(ctx.channel());
      } else {
          // 向客户端发送握手消息
          ChannelFuture future = handshaker.handshake(ctx.channel(), request);
          if (future.isSuccess()) {
              // WebSocket连接建立成功
      
              // 将当前连接保存到ChannelGroup中
              channelGroup.add(ctx.channel());
          }
      }
      

      }

      // 推送消息给所有客户端 private void sendMessageToAllClients(Message message) { // 将消息加入消息队列中 messageQueue.offer(message);

      // 广播消息给所有客户端
      for (Channel ch : channelGroup) {
          if (ch.isActive()) {
              ch.writeAndFlush(new TextWebSocketFrame("push:" + message.getContent()));
          }
      }
      

      }

      // 接收客户端发送的消息 @Override protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception { if ("heartbeat".equals(msg.text())) { // 心跳消息,不做处理 return; }

      // 将客户端发送的消息转换成Message对象,并且推送给所有客户端
      Message message = convertToMessage(msg.text());
      sendMessageToAllClients(message);
      

      }

      前端代码示例:

      // 建立WebSocket连接 var ws = new WebSocket("ws://localhost:8888/websocket");

      // 监听WebSocket连接 ws.onopen = function() { console.log("WebSocket连接已建立"); };

      // 监听WebSocket消息 ws.onmessage = function(event) { console.log("接收到消息:" + event.data); };

      // 向服务器发送消息 ws.send("hello");

      以上代码示例仅供参考,具体实现细节需要根据实际需求进行相应的修改和调整。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 6月9日
  • 已采纳回答 6月1日
  • 创建了问题 6月1日

悬赏问题

  • ¥15 欧拉系统opt目录空间使用100%
  • ¥15 ul做导航栏格式不对怎么改?
  • ¥20 用户端如何上传图片到服务器和数据库里
  • ¥15 现在研究生在烦开题,看了一些文献,但不知道自己要做什么,求指导。
  • ¥30 vivado封装时总是显示缺少一个dcp文件
  • ¥100 pxe uefi启动 tinycore
  • ¥15 我pycharm运行jupyter时出现Jupyter server process exited with code 1,然后打开cmd显示如下
  • ¥15 可否使用carsim-simulink进行四轮独立转向汽车的联合仿真,实现四轮独立转向汽车原地旋转、斜向形式、横移等动作,如果可以的话在carsim中如何进行相应设置
  • ¥15 Caché 2016 在Java环境通过jdbc 执行sql报Parameter list mismatch错误,但是同样的sql使用连接工具可以查询出数据
  • ¥15 疾病的获得与年龄是否有关