Client-server communication in Node.js

陌路散爱 提交于 2021-01-27 12:50:54

问题


I've recently been getting in to node.js in order to make an online game (for education). Through reading various tutorials I've come up with the simple code shown below. With the code I have I'm capable of client-server communication, which is mostly all I need in order to make the game. There's only one problem, only the client can initiate conversation whereas the server can only respond. In addition to this, I also need to at any moment in time send the current game state from the server to the client. For example, in a 2 player game, when a player sends a command that alters the game state, that new game state needs to be forwarded to BOTH players.

Is there a simple way in node.js to do this? I know that you can't simply send a message to the client since the client cannot be expected to have a port opened for the server to use, but maybe there's a way for the client to leave behind a connection for the server to use? I'm the kind of guy that learns by example, thus some simple working code would be appreciated.

Btw, I'm hosting the game on firebase, in case that's relevant.

index.js:

const functions = require('firebase-functions');
const express = require('express');

const app = express();

app.post('/game', (request, response) => {
    request.body.randomNumber = Math.random();
    console.log(request.body);
    response.json(request.body);
});

exports.app = functions.https.onRequest(app);

index.html:

<!DOCTYPE html>
<html>
  <head>
    <title>Page Title</title>
  </head>
  <body>

    <input type="text" id="commandbox" onkeypress="send(this)">
    <br>
    <div id="display"></div>

    <script>
      const send = (ele) => {
        if (event.key === 'Enter') {
          console.log(ele.value);
          const json = {
            name: "John",
            gender: "male",
            age: 25, 
            message: ele.value
          };
          postToGame(json);
        }
      };
    </script>

    <script>
      const postToGame = (json) => {
        const xhr = new XMLHttpRequest();
        xhr.open("POST", '/game', true);
        xhr.setRequestHeader("Content-type", "application/json");
        xhr.onload = () => {
          if (xhr.readyState == 4 && xhr.status == 200) {
            document.getElementById("display").innerHTML = xhr.responseText;
          }
        };
        xhr.send(JSON.stringify(json));
      }
    </script>

  </body>
</html>

回答1:


I would use websockets for this. Once you've set up the connection you can initiate messages from either side. The WS npm package makes this pretty easy.

Server example (using the ws npm package):

    const WebSocket = require('ws');

    // Set up server
    const wss = new WebSocket.Server({ port: 8080 });

    // Wire up some logic for the connection event (when a client connects) 
    wss.on('connection', function connection(ws) {

      // Wire up logic for the message event (when a client sends something)
      ws.on('message', function incoming(message) {
        console.log('received: %s', message);
      });

      // Send a message
      ws.send('Hello client!');
    });

Client example (no need for any package here, it's built into most browsers) :

// Create WebSocket connection.
const socket = new WebSocket('ws://localhost:8080');

// Connection opened
socket.addEventListener('open', function (event) {
    socket.send('Hello Server!');
});

// Listen for messages
socket.addEventListener('message', function (event) {
    console.log('Message from server ', event.data);
});

There are alternatives if you can't use websockets, such as polling (where the client periodically calls the server to see if theres a message), and long-polling (where the server holds a http request open for an artificially long period of time until a message is ready).




回答2:


The Firebase Realtime Database is another alternative.

https://github.com/firebase/quickstart-js/blob/master/database/scripts/main.js

<!-- index.html file in client browser -->
<script src="/__/firebase/5.5.0/firebase-app.js"></script>
<script src="/__/firebase/5.5.0/firebase-auth.js"></script>
<script src="/__/firebase/5.5.0/firebase-database.js"></script>
<script src="/__/firebase/init.js"></script>

<script src="scripts/main.js"></script>

<!-- main.js file in client browser -->
// Create new comment.
// createNewComment, commentInput, addCommentForm is defined in the main.js
addCommentForm.onsubmit = function(e) {
    e.preventDefault();
    createNewComment(postId, firebase.auth().currentUser.displayName, uid, commentInput.value);
    commentInput.value = '';
    commentInput.parentElement.MaterialTextfield.boundUpdateClassesHandler();
};
// Listen for comments.
// addCommentElement, postElement is defined in the main.js
var commentsRef = firebase.database().ref('post-comments/' + postId);
commentsRef.on('child_added', function(data) {
    addCommentElement(postElement, data.key, data.val().text, data.val().author);
});


来源:https://stackoverflow.com/questions/52407025/client-server-communication-in-node-js

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!