从服务器(`node.js`)而不是从客户端

时间:2019-02-04 07:25:43

标签: node.js sockets socket.io publish-subscribe

我正在尝试使用node.jssocket.io制作游戏服务器。

基本概念如下。

  • 服务器启动时初始化socket.io实例
  • 将实例存储在全局范围内,以便控制器可以访问它
  • 调用API时,我们会在控制器中触发一些socket.io事件或其他一些问题

这是我所做的实现...

首先,在server.js-入口点

let GlobalVars = require('./state/GlobalVars');
const apiRouters = require('./router');

...

app.use('/api', apiRouters);
app.get('/', (req, res) => {
    res.sendFile(`${__dirname}/test/simpleClient.html`)
});

const httpServer = http.createServer(app);
let socketIOInstance = socketIO(httpServer);
socketIOInstance.on('connection', (socket) => {
    console.log('SOCKET.IO A USER CONNECTED');
    socket.on('create', (data) => {
        console.log('SOCKET.IO create called', socket);
        socket.join(data.room);
        socketIOInstance.emit('message', 'New people joined');
    });
    socket.on('join', (data) => {
        console.log('SOCKET.IO join called', data);
    })
    socket.emit('message', 'Hi');
});
GlobalVars.socketIO = socketIOInstance; 
// Add to global, so the controllers can manage own actions like create, join ...
httpServer.listen(port, () => {
    console.log(`Server Listening on the port ${port}`);
})
...

从客户端访问时,我可以在浏览器控制台中看到SOCKET.IO A USER CONNECTEDHi

第二,在api控制器中。

let GlobalVars = require('../state/GlobalVars');
...

router.post('/create', (req, res) => {
  console.log('GenerateGameSokect');
  let game = new Game();
  let gameId = game.gameId;
  // console.log('Global vars ', GlobalVars.socketIO);
  GlobalVars.socketIO.emit('create', {
    room: gameId
  });
  res.json({
    result : 'SUCCESS',
    game : game
  })
});

我导入了包含套接字IO实例的GlobalVars。因此,我所期望的是,从语句create触发了套接字GlobalVars.socketIO.emit('create', Object)事件,但在服务器日志中找不到消息。

我不知道自己缺少什么。

我追求的最终形式类似于...

  • 当用户调用create API时,我会创建套接字连接和空间
  • API将使用HTTP协议进行调用,但是在API中,服务器会发布一些事件。 -喜欢pubsub。

感谢您阅读我的问题b。 Here is full source code till now(bitbucket public)

==================编辑==================

我了解了(也许...)

我想要的用户流是...

  1. 客户端调用API
  2. (在服务器中)检查API中的验证,如果有效则发送到socket.io
  3. 如果事件被接受,则将新状态发送给所有客户

但是,在服务器中创建socket.io连接对我来说很奇怪,解决方案取决于客户端。

我将更改的新用户流

  1. 客户端调用验证API
  2. 如果return有效,则客户端发出socket.io事件。这次服务器仅进行验证,不发出socket.io
  3. 在套接字事件中,将新状态发送给所有其他用户

==================编辑#2 ==================

这是一种结论。看来我只是误解了套接字通信的概念。就像答案和答复说的那样,SocketHTTP是完全不同的渠道,无法将两者连接起来。 (至少在没有打开从http服务器到套接字的新连接的情况下)

如果这是错误的,您可以添加回复,谢谢

1 个答案:

答案 0 :(得分:0)

现在我了解你了。或者至少我认为!

让我们这样说:套接字(socket)上有两个(不对称的)侧面,服务器和客户端。在对您的帖子的评论中,我分别称其为“全球经理”和“插座”。

const server = require('socket.io')(yourHttpServer);
// client is installed as well when `npm i socket.io`
const client = require('socket.io-client')('http://localhost:' + yourServerPort);

// `socket` is the server side of the socket
server.on('connection', (socket) => {
  // this will be triggered by client sides emitting 'create'
  socket.on('create', (data) => {
    console.log('a client socket just fired a "create" event!');
  });
});

// this will be triggered by server side emitting 'create'
client.on('create', (data) => {
  server.emit('create', {content: 'this will result in an infinite loop of "create" events!'});
});

在您的/create路由中,当您GlobalVars.socketIO.emit('create', ...)时,不会触发服务器端套接字处理程序,但是,如果您有通过浏览器连接的客户端(或者,如我上面所示,如果您直接从服务器连接客户端套接字),然后它们将触发其'create'监听器(如果有)。

希望这可以帮助您走上正确的轨道!