You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js环境Socket.IO请求6次后无法获取ID问题求助

问题根因

  • 最核心的问题是你的POST路由没有给客户端返回任何响应,也没有主动结束请求。主流浏览器对同一个域名的并发请求上限默认是6个,前6次请求发出后一直处于等待响应的挂起状态,后续的请求会被浏览器暂存在本地队列中,不会实际发送到服务端,所以你看不到后续的id打印。服务端重启后,之前挂起的请求会重新发起,所以会一次性收到之前所有的id。
  • 你创建的clientUDP套接字没有用let/const声明,属于全局变量,每次请求都会覆盖上一次的实例,还会造成内存和文件描述符泄漏,请求次数多了会触发资源上限。
  • UDP套接字使用完成后没有主动关闭,一直占用系统资源。
  • 若你没有在其他地方配置express的body解析中间件,req.body会是undefined,也会导致拿不到id。

修复方案

修改后的代码如下:

const express = require("express");
const dgram = require('dgram');
// 替换为实际的UDP服务配置
const UDP_PORT = 1234;
const UDP_HOST = '127.0.0.1';
var closeFlag = false;
const PORT = process.env.SERVER_PORT || 3000; 
const app = express();
// 新增body解析中间件,用于解析POST请求体
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
var count = 1;
const http = require('http');
http.globalAgent.maxSockets = 100;
http.Agent.maxSockets = 100;
const serverTCP = http.createServer(app)

const tcpsock = require('socket.io')(serverTCP, {
  cors: {
    origin: '*',
  },
  perMessageDeflate: false 
});

app.post("/getchanneldata", (req, res) => {
  console.log("count : "+count)
  count++;
  closeFlag = false;
  const message = (req.body.val).toString()
  console.log("message : "+message);
  // 改为局部变量,避免全局污染
  const chanId = message;

  // 用const声明局部UDP实例,避免覆盖全局变量
  const client = dgram.createSocket({ type: 'udp4', reuseAddr: true });
  
  client.on('listening', () => {
    const address = client.address();
  });

  client.on('message', function (message1, remote) {
    const arr = message1.toString().split(',');
    // 此处可添加Socket.IO推送逻辑,把数据推送给前端
    tcpsock.emit('channelData', { id: chanId, data: arr });
    // 处理完成后关闭UDP套接字释放资源
    client.close();
    // 主动返回HTTP响应,结束当前请求
    res.send({ code: 200, data: arr });
  }); 

  client.send(message, 0, message.length, UDP_PORT, UDP_HOST, function (err, bytes) {
    if (err) {
      console.error('UDP消息发送失败:', err);
      client.close();
      // 出错也要返回响应,避免请求一直挂起
      res.status(500).send({ code: 500, msg: '请求失败' });
      return;
    }
    console.log(message);
    console.log('UDP client message sent to ' + UDP_HOST + ':' + UDP_PORT);
  });

  client.on('close', () => {
    console.log('UDP套接字已释放');
  });

  // 新增错误捕获,避免单个请求异常导致服务崩溃
  client.on('error', (err) => {
    console.error('UDP套接字异常:', err);
    client.close();
    res.status(500).send({ code: 500, msg: err.message });
  });
});

serverTCP.listen(PORT, () => {
  console.log('服务已启动,端口:', PORT);
});
  • 每一次请求处理完成或出错时都主动返回HTTP响应,结束请求,避免占用并发连接配额。
  • 所有变量使用const/let声明,避免全局变量污染。
  • UDP套接字使用完成后主动关闭,避免资源泄漏。
  • 补充错误处理逻辑,提升服务稳定性。

内容的提问来源于stack exchange,提问作者salik saleem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 14:54:04