无法在nodejs服务器

时间:2016-04-26 05:34:26

标签: javascript node.js websocket socket.io

我有2台相互通信的服务器。当用户想要检查传感器的运行状况时,它会访问API / check / health,然后与监控服务器通话以获取传感器的状态字段。此状态将发送回供应并发送给用户。 / p>

我对此进行了测试,它运行正常..当我执行http://localhost:3000/check/health/4时(3是传感器ID),我得到的答案为好。当我做另一个请求http://localhost:3000/check/health/3时,我在配置服务器上收到错误,如下所示:

有谁知道为什么我不能做第二次GET请求..我似乎只为第一次健康检查而不是后续的健康检查...

输出/错误:

服务器在端口3000监听 连接到监控服务器!
服务器获得了传感器ID的健康检查:4
传感器的状态为:良好
服务器获得了传感器ID的健康检查:3
传感器的状态为:未定义
_http_outgoing.js:344个
      抛出新错误('不能在发送后设置标题。');
      ^

错误:发送后无法设置标题 在ServerResponse.OutgoingMessage.setHeader(_http_outgoing.js:344:11)

配置服务器:

// Code to communicate with Monitoring server
var io = require('socket.io-client');
var socket = io.connect('http://localhost:4000', { reconnect: true });
socket.on('connect', function(socket) {
  console.log('Connected to Monitoring Server!');
});

// Code to serve the Sensor users
var express = require('express');
var app= express();
var path = require('path');
var bodyParser= require('body-parser');

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/sensor_db');
var Schema = mongoose.Schema;

var sensorSchema = new Schema({
  value:{ type:Number, default:0},
  format:{type:String, default:"default"},
  id:{type:Number,required:true,unique:true},
  description:{type:String},
  type:{type:String},
  groupId:{type:Number},
  users:{type:Array,default:[]},
  admin:{type:String,default:'Undefined'},
  status:{type:String,default:'InActive'},
  owner:{type:String,default:'Undefined'},
  templateId:{type:Number}

});
var Sensor = mongoose.model('Sensor',sensorSchema);

// API to get the health of the Sensor by looking up its Status, pass the Sensor ID to check
app.get('/check/health/:id', function (req, res) {

  var id = req.params.id;
  console.log("Server got a health check for Sensor ID :", id);
  socket.emit('eventToClient',{ id: id })
  socket.on('reply', function (data) {
    console.log("The Status of the Sensor is :",data.status);
    res.json(data.status);
  });
})

app.listen(3000);
console.log('Server listening at port 3000');

监控服务器:

var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var express = require('express');

var mongoose = require('mongoose');
mongoose.connect('mongodb://127.0.0.1:27017/sensor_db') ;
var Schema = mongoose.Schema;

var sensorSchema = new Schema({
  value:{ type:Number, default:0},
  format:{type:String, default:"default"},
  id:{type:Number,required:true,unique:true},
  description:{type:String},
  type:{type:String},
  groupId:{type:Number},
  users:{type:Array,default:[]},
  admin:{type:String,default:'Undefined'},
  status:{type:String,default:'Undefined'},
  owner:{type:String,default:'Undefined'},
  templateId:{type:Number}

});
var Sensor = mongoose.model('Sensor',sensorSchema);

io.on('connection', function(socket){
  console.log('connection received from Provisioning');
  // To get messages from Provisioning server
  socket.on('eventToClient',function(data) {
    var id = data.id
    Sensor.findOne({id: id}, function (err, doc) {
      if (err) return res.status(500).send({error: err});
      socket.emit('reply',doc)

    })
  });
});

server.listen(4000, function(){
  console.log('socket.io server listening on *:4000');
});

4 个答案:

答案 0 :(得分:0)

您遇到此问题,因为当您访问/check/health/3时,它会发出eventToClient事件并等待来自监控服务器的reply事件。但是,同时它等待回复,端点退出。

一段时间后,当您收到reply事件时,您会尝试发送res.json。但是,res已经结束了。这就是您收到Can't set headers after they are sent.错误的原因。

答案 1 :(得分:0)

这是一个有趣的问题。

当您点击配置服务器/check/health/:id上的端点时,每次创建一个新的套接字事件侦听器。

第一次它起作用是因为只有一个听众期待'回复' - 但是下次你到达终点时有两个竞争的听众。第一个侦听器发送响应,在您收到该响应之前,第二个侦听器已尝试设置标头并出错。

答案 2 :(得分:0)

我认为 res 变量正在失去其上下文。由于socket.on('eventToClient',Fn)是一个事件侦听器,仅在触发特定事件时触发。它是一个成功的回叫类型功能。好像你也把socket.on('eventToClient',Fn)放在get端点之外,它仍然会被解雇。它只附加了事件监听器时的res上下文。因此,一旦res发送给第一个请求,下次上下文过期。

更新:检查以下代码更改

配置服务器:

// Code to communicate with Monitoring server
var io = require('socket.io-client');
var socket = io.connect('http://localhost:4000', { reconnect: true });
socket.on('connect', function(socket) {
  console.log('Connected to Monitoring Server!');
});

// Code to serve the Sensor users
var express = require('express');
var app= express();
var path = require('path');
var bodyParser= require('body-parser');

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/sensor_db');
var Schema = mongoose.Schema;

var sensorSchema = new Schema({
  value:{ type:Number, default:0},
  format:{type:String, default:"default"},
  id:{type:Number,required:true,unique:true},
  description:{type:String},
  type:{type:String},
  groupId:{type:Number},
  users:{type:Array,default:[]},
  admin:{type:String,default:'Undefined'},
  status:{type:String,default:'InActive'},
  owner:{type:String,default:'Undefined'},
  templateId:{type:Number}

});
var Sensor = mongoose.model('Sensor',sensorSchema);
var healthResObj = {};

socket.on('reply', function (data) {
    console.log("The Status of the Sensor is :", data.result.status);
    healthResObj[data.resKey].json(data.result.status); // get the response object from by providing its key
 delete healthResObj[data.resKey]; //remove the object from memory
  });

// API to get the health of the Sensor by looking up its Status, pass the Sensor ID to check
app.get('/check/health/:id', function (req, res) {

  var id = req.params.id;
  console.log("Server got a health check for Sensor ID :", id);
  socket.emit('eventToClient',{ id: id })
  var key = Date.now();
  healthResObj[key] = res;
  socket.emit('eventToClient',{ id: id , resKey: key}); // pass the key where the response object stored so that can be retrieved later 
})

app.listen(3000);
console.log('Server listening at port 3000');

监控服务器:

var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var express = require('express');

var mongoose = require('mongoose');
mongoose.connect('mongodb://127.0.0.1:27017/sensor_db') ;
var Schema = mongoose.Schema;

var sensorSchema = new Schema({
  value:{ type:Number, default:0},
  format:{type:String, default:"default"},
  id:{type:Number,required:true,unique:true},
  description:{type:String},
  type:{type:String},
  groupId:{type:Number},
  users:{type:Array,default:[]},
  admin:{type:String,default:'Undefined'},
  status:{type:String,default:'Undefined'},
  owner:{type:String,default:'Undefined'},
  templateId:{type:Number}

});
var Sensor = mongoose.model('Sensor',sensorSchema);

io.on('connection', function(socket){
  console.log('connection received from Provisioning');
  // To get messages from Provisioning server
  socket.on('eventToClient',function(data) {
    var id = data.id
    Sensor.findOne({id: id}, function (err, doc) {
      if (err) return res.status(500).send({error: err});
      socket.emit('reply',{result:doc, resKey: data.resKey}); //forwarding the resKey( the key of the response);

    })
  });
});

server.listen(4000, function(){
  console.log('socket.io server listening on *:4000');
});

答案 3 :(得分:0)

您可以通过更新配置端点来始终返回OK但离开socket.on('reply', function())

来证明我的观点
app.get('/check/health/:id', function (req, res) {

  var id = req.params.id;
  console.log("Server got a health check for Sensor ID :", id);
  socket.emit('eventToClient',{ id: id })
  socket.on('reply', function (data) {
    console.log("The Status of the Sensor is :",data.status);
  });
  res.json("ok")
})

您首先会看到“回复”中的1条回复'然后2 ...然后3

Server got a health check for Sensor ID : 3
The Status of the Sensor is : Good
Server got a health check for Sensor ID : 3
The Status of the Sensor is : Good
The Status of the Sensor is : Good
Server got a health check for Sensor ID : 3
The Status of the Sensor is : Good
The Status of the Sensor is : Good
The Status of the Sensor is : Good