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

Node.js TCP socket服务端存储GPS设备数据到数组复用及数据混淆排查

问题核心原因
  • 全局/外层作用域变量污染:你定义的car_id、car_no、car_username、index都是外层作用域的共享变量,TCP服务是并发处理多连接的,不同设备的上报请求会同时覆盖这些变量的值,直接导致不同设备的数据串用。
  • 异步函数时序错误:getCarDetails是异步IO操作,你在if (find_string === -1)分支里将index = length - 1写在回调函数外部,此时数据库查询还没返回,socketarray.push根本没有执行,拿到的length是旧数组的长度,index值完全错误,后续用这个索引修改数组自然会操作到其他设备的条目。
  • 数据存储结构不合理:用数组存储+findIndex遍历查找的方式效率低,且并发push时容易出现索引偏移,同时没有绑定socket实例与对应设备信息,连接断开后也没有清理旧数据,进一步加剧数据混乱。
修复方案
  1. 移除所有共享的全局变量,设备信息要么绑定到对应socket实例上,要么使用Map结构以car_id为key存储,避免索引错乱。
  2. 所有需要使用数据库查询结果的逻辑,全部放到getCarDetails的回调内部执行,保证异步逻辑执行完成后再操作对应数据。
  3. socket断开连接时,及时清理存储的对应设备数据,避免旧数据干扰。
修复后参考代码
const Net = require('net');
// 用Map存设备信息,key为car_id,查询效率更高
const carMap = new Map();
const server = new Net.Server();
const HOST = "IP";
const PORT = 8888;

server.listen(PORT, HOST);
server.on('connection', function(socket) {
  console.log('A new connection has been established.');
  // 每个socket单独绑定自己的car信息,不共享
  socket.carInfo = null;

  socket.on('data', async function(data) {
    const server_data = data.toString();
    const car_details = server_data.split(',').filter(str => str != "");
    const car_id = car_details[0];

    let currentCarInfo = null;
    // 先查Map里有没有该设备信息
    if (carMap.has(car_id)) {
      currentCarInfo = carMap.get(car_id);
      socket.carInfo = currentCarInfo;
    } else {
      // 新设备查数据库,所有后续逻辑放回调里
      getCarDetails(car_id, function(dbRes) {
        if (!dbRes) return;
        currentCarInfo = {
          car_id: "" + car_id,
          car_no: dbRes.car_no,
          car_username: dbRes.username,
          socket: socket // 可选,绑定socket实例
        };
        carMap.set(car_id, currentCarInfo);
        socket.carInfo = currentCarInfo;
        // 这里写新设备查询完成后的后续业务逻辑
        handleBusinessLogic(socket.carInfo, data);
      });
      // 异步未返回前直接返回,不要执行后续逻辑
      return;
    }
    // 已有设备信息的情况下执行业务逻辑
    handleBusinessLogic(currentCarInfo, data);
  });

  socket.on('end', function() {
    console.log('Closing connection with the client');
    // 断开连接时清理数据
    if (socket.carInfo?.car_id) {
      carMap.delete(socket.carInfo.car_id);
    }
  });

  socket.on('error', function(err) {
    console.log(`Error: ${err}`);
  });
});

// 业务逻辑单独抽离,直接传当前设备信息,不用依赖全局变量
function handleBusinessLogic(carInfo, data) {
  // 这里直接用传入的carInfo操作,比如修改用户名:
  // carInfo.car_username = "bello";
  // 写数据库也直接用carInfo里的id,不会串数据
}

function getCarDetails(car_id,callback) {
  console.log("db called");
  db.getConnection((err, connection) => {
    if(err){
      console.log("error is" + err);
      return callback(false);
    }
    console.log('connected as id ' + connection.threadId);
    let selectQuery = 'SELECT * FROM ?? WHERE ?? = ?';
    let query = mysql.format(selectQuery, ["car", "id", car_id]);
    connection.query(query, (err, data) => {
      connection.release();
      if(err) {
        console.error(err);
        return callback(false);
      }
      if(data.length > 0){
        return callback(data[0]);
      } else{
        return callback(false);
      }
   });
  });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 04:36:05