Инициировать событие `socket.io` с сервера (` node.js`), а не с клиента - PullRequest
0 голосов
/ 04 февраля 2019

Я пытаюсь сделать игровой сервер с node.js, socket.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 CONNECTED и Hi в консоли браузера.

Во-вторых, в контроллере 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
  })
});

Я импортировал GlobalVars, который содержит экземпляр socketIO.Поэтому я ожидал, что событие сокета create сработало из оператора GlobalVars.socketIO.emit('create', Object), но не смог найти сообщение в журналах сервера.

Я не понял, чего мне не хватало.

окончательная форма, которую я использую, выглядит примерно так: *

  • Когда пользователь вызывает API для создания, я создаю соединение через сокет, и API
  • будет вызываться в протоколе HTTP, но в APIСервер публикует некоторые события.- вроде pubsub.

Спасибо за чтение моих вопросов b. Здесь приведен полный исходный код до сих пор (общедоступная информация)

================== РЕДАКТИРОВАТЬ ====================

Я понял (возможно ...)

Поток пользователей, которого я хотел, был ...

  1. API вызова клиента
  2. (на сервере) Проверка валидации в API и, если она действительна, отправка socket.io
  3. Если событие принято, отправить новый статус всем клиентам

Однако создание socket.io соединения на сервере выглядит для меня странно, решение остается за клиентом.

Новый пользовательский поток я изменю

  1. Клиентвызовите API проверки
  2. Если возвращение допустимо, клиентское событие emit socket.io.На этот раз сервер только выполняет проверку, но не отправляет socket.io
  3. В случае события socket отправьте новый статус всем другим пользователям

================== РЕДАКТИРОВАТЬ # 2 ====================

Это своего рода заключение.Похоже, я просто неправильно понял концепцию сокетной связи.Как и в ответе и ответе, Socket и HTTP - это совершенно разные каналы, и нет возможности соединить оба.(По крайней мере, без открытия нового соединения с http-сервера на сокет)

Если это не так, вы можете добавить ответ, Спасибо

1 Ответ

0 голосов
/ 04 февраля 2019

Теперь я вас понимаю.Или, по крайней мере, я так думаю!

Скажем так: на сокете, сервере и клиенте есть две (асимметричные) стороны.То, что я назвал, соответственно, «глобальный менеджер» и «сокет» в своем комментарии к вашему сообщению.

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' слушатель, если таковой имеется.

Надеюсь, это поможет вам встать на правильный путь!

...