我在单独的模块中声明套接字服务器。我可以在应用程序的任何地方访问服务器的对象,例如我可以发出声明。但我无法在路线中添加听众,例如:
router.post('/example', function(req, res, next) {
var socketio = req.app.get('sock');
socketio.sockets.on('connection', function (socket) {
socket.on('message', function (text) {
console.log('ok');
});
});
有没有办法做到这一点?
答案 0 :(得分:0)
如果只有一个设备要与之通信并且它应该已经连接到您的服务器而req.app.get('sock')
是您访问socketio
服务器对象的方式,那么您可以这样做它是这样的:
var theDeviceSocket;
req.app.get('sock').on('connection', function(socket) {
theDeviceSocket = socket;
});
router.post('/example', function(req, res, next) {
if (theDeviceSocket) {
theDeviceSocket.emit("someMsg", "someData");
}
// send whatever response you want to send
res.end();
});
如果你试图从单个设备获得响应并将其作为对POST的响应返回,那么你可以这样:
// store the one connection to/from the special device
var theDeviceSocket;
// keep a request cntr so we can tell which response goes with which request
var requestCntr = 0;
req.app.get('sock').on('connection', function(socket) {
theDeviceSocket = socket;
});
router.post('/example', function(req, res, next) {
var timer, thisRequestId;
function gotData(data) {
// if this is our specific response
if (data.requestId === thisRequestId) {
theDeviceSocket.removeListener("someMsgResponse", gotData);
res.send(data);
clearTimeout(timer);
}
}
if (theDeviceSocket) {
theDeviceSocket.on("someMsgResponse", gotData);
thisRequestId = requestCntr++;
theDeviceSocket.emit("someMsg", {requestId: thisRequestId});
// set up a timeout in case we don't get the proper response
timer = setTimeout(function() {
theDeviceSocket.removeListener("someMsgResponse", gotData);
res.send("error");
}, 5000);
}
});
第二种方案很复杂,因为您已将此架构设计为请求/响应方案,但socket.io不是请求/响应协议。因此,为了知道哪个响应属于哪个请求(当可能有多个客户端同时与服务器交互时),您必须在通过socket.io发送和接收的数据中实现某种requestId。这意味着您必须更改设备以回显您通过响应发送的requestId。如果您使用专为请求/响应设计的协议(如HTTP而不是socket.io),则所有这些都不是必需的。