Socket.io-在服务器上调用错误的客户端套接字事件

时间:2018-11-08 00:49:53

标签: node.js socket.io

我正在为我的socket.io应用程序创建一个负载测试应用程序。当服务器端发生数据库错误时,会发生非常奇怪的结果。在DB死锁时,服务器会发出正确的事件,但在客户端会调用错误的事件。

服务器代码:

(I even got rid of all DB code and just output what the DB would output so
 I know it's nothing to do with the DB)
function AddUser(gObj, cb) {
  if (gObj.UKEY==2)
    cb({err: 901, errm: "deadlock baby"});
  else if (gObj.UKEY==3)
    cb(null, [3,0,0,1,0]);
  else
    cb(null, [1,1,0,1,0]);
}

var io=require('socket.io')(8080);
var iowm = io.of('/mpp');
iowm.on('connection', function(socket) {
  console.log('in MPP connection');
  socket.on('nu', function(data) {
    console.log('APP: in AddUser');
    AddUser(data, function(err, result) {
      console.log('RC: ',data);
      if (err) {
        console.log(err);
        iowm.emit('error', {ERRM: err.errm});
        console.log('ERROR: emitted');
      } else {
        console.log('done: ',result);
        iowm.emit('done', result);
      }
    });
  });
});

io.httpServer.on('listening', function() {
  console.log('listening on port ',io.httpServer.address().port);
});
console.log('Done...');

客户代码:

(我将套接字事件包装在包装函数中(这可能是我的错误所在),以便在此紧密循环中将正确的参数传递给套接字事件)

for(var i=0; i<args[4]; i++) {
  age = (Math.floor(Math.random()*args[3]) + 1) * 4;
  console.log('ukey: '+args[2],'   age: ',age);
  socket = io.connect('http://localhost:8080/mpp');
  if (socket) {
    var OrigSocketOn = socket.on;
    socket.on = function(event, data, cb2) {
      return OrigSocketOn.call(socket, event, function(res) {
        console.log('ESock: ', event,'  data: ',data);
        switch(data.ENT) {
          case 2:    // connect
            cb2(data);
            break;
          case 3:    // error
            cb2({data: data, result: res});
            break;
          default:
            cb2(res);
            break;
        }
      });
    };
    socket.on('connect', {ENT: 2, GKEY: args[1], UKEY: args[2], AGE: age}, function(data) {
      socket.emit('nu', {GKEY: data.GKEY, UKEY: data.UKEY, AGE: data.AGE});
    });
    socket.on('done', {ENT: 4, UKEY: args[2], AGE: age}, function(data) {
      ++cnt;
      console.log('SOCKET: NewUser Done cnt: ',cnt);
      console.log(data);
      socket.close();
      if (cnt == args[4] || data[4]>0)
        cb();
    });
    socket.on('error', {ENT: 3, GKEY: args[1], UKEY: args[2], AGE: age}, function(data) {
      console.log('SOCKET: NewUser Err');
      console.log(data);
      if (data.result.ERRM.indexOf('deadlock') > -1) {   // deadlock - try again
        socket.emit('nu', {GKEY: data.GKEY, UKEY: data.UKEY, AGE: data.AGE});
      } else {
        socket.close();
        if (++cnt == args[4])
          cb();
      }
    });
...

服务器输出:

(一切看起来不错。UKEY1和3恢复正常,并发出'done'事件。但是UKEY == 2是死锁的条目,因此它发出'error'事件。

in MPP connection
in MPP connection
in MPP connection
APP: in AddUser
RC:  { GKEY: 1, UKEY: 3, AGE: 32 }
done:  [ 3, 0, 0, 1, 0 ]
APP: in AddUser
RC:  { GKEY: 1, UKEY: 1, AGE: 40 }
done:  [ 1, 1, 0, 1, 0 ]
APP: in AddUser
RC:  { GKEY: 1, UKEY: 2, AGE: 40 }
{ err: 901, errm: 'deadlock baby' }
ERROR: emitted

客户端输出:(这是问题)

ukey: 1    age:  40
ukey: 2    age:  40
ukey: 3    age:  32
ESock:  connect   data:  { ENT: 2, GKEY: 1, UKEY: 1, AGE: 40 }
ESock:  connect   data:  { ENT: 2, GKEY: 1, UKEY: 2, AGE: 40 }
ESock:  connect   data:  { ENT: 2, GKEY: 1, UKEY: 3, AGE: 32 }
ESock:  done   data:  { ENT: 4, UKEY: 1, AGE: 40 }
SOCKET: NewUser Done cnt:  1
[ 3, 0, 0, 1, 0 ]
ESock:  done   data:  { ENT: 4, UKEY: 2, AGE: 40 }
SOCKET: NewUser Done cnt:  2
[ 3, 0, 0, 1, 0 ]
ESock:  done   data:  { ENT: 4, UKEY: 1, AGE: 40 }
SOCKET: NewUser Done cnt:  3
[ 1, 1, 0, 1, 0 ]

那么3个问题:

1)客户端“完成”事件看似被调用了3次,而应该只有2次,而“错误”事件应被调用一次。

2)第1和第3个“完成”事件的数据相同(UKEY:1),应分别为(UKEY:1)和(UKEY:3)

3)(UKEY:3)根本没有输出数据。

1 个答案:

答案 0 :(得分:1)

在我看来,您在iowm.emit(...)的服务器上应该做socket.emit(...)

您的客户端显然正在与服务器建立多个连接,因为io.connect()循环中有一个for(var i=0; i<args[4]; i++)。因此,当您在服务器上执行iowm.emit(...)时,它将向客户端发送所有连接,而不仅仅是发生错误的连接。

  

1)客户端“完成”事件看似被调用了3次,而应该只有2次,而“错误”事件应被调用一次。

因为您正在将错误传播给所有客户端连接,而不仅仅是错误发生的那一个socket