web-dev-qa-db-fra.com

Envoi de message à un utilisateur connecté spécifique via webSocket?

J'ai écrit un code pour diffuser un message à tous les utilisateurs :

Le code utilisé: (bref)

// websocket and http servers
var webSocketServer = require('websocket').server;

...
...
var clients = [ ];

var server = http.createServer(function(request, response) {
    // Not important for us. We're writing WebSocket server, not HTTP server
});
server.listen(webSocketsServerPort, function() {
  ...
});

var wsServer = new webSocketServer({
    // WebSocket server is tied to a HTTP server. 
    httpServer: server
});


    // This callback function is called every time someone
    // tries to connect to the WebSocket server
    wsServer.on('request', function(request) {
    ...
    var connection = request.accept(null, request.Origin); 
    var index = clients.Push(connection) - 1;
    ...

S'il vous plaît noter:

  • Je n'ai pas de référence utilisateur mais seulement une connexion.
  • Toutes les connexions utilisateurs sont stockées dans un array.

Goal: supposons que le serveur NodeJs veuille envoyer un message à un client spécifique (John).

Et voici la question:

  • Comment le serveur NodeJs pourrait-il savoir quelle connexion a John?

    Le serveur NodeJs ne connaît même pas John. tout ce qu'il voit, ce sont les connexions.

Donc, je crois que maintenant, je ne devrais pas stocker les utilisateurs uniquement par leur connexion. Au lieu de cela, je dois stocker un object - qui contiendra le userId et le connection objet.

Et voici mon idée:


  • Une fois la page chargée (Dom ready) - établissez une connexion avec le serveur NodeJs.

  • Lorsque le serveur NodeJs accepte une connexion, générez une chaîne unique et envoyez-la au navigateur client. Stocke la connexion utilisateur et la chaîne unique dans un objet. par exemple{UserID:"6" , value :{connectionObject}}

  • Du côté du client, lorsque ce message arrive, enregistrez-le dans un champ ou un cookie masqué. (pour les futures demandes au serveur NodeJs)


Lorsque le serveur veut envoyer un message à John:

  • Recherchez l'ID utilisateur de John dans le dictionnaire et envoyez un message par la connexion correspondante.

s'il vous plaît noter qu'il n'y a pas de code de serveur asp.net invloced ici (dans le mécanisme de message). seulement NodeJs.

Question:

Est-ce la bonne façon de faire? (ou ai-je raté quelque chose?)

64
Royi Namir

Ce n'est pas seulement la bonne façon de faire, mais la seule façon. Fondamentalement, chaque connexion nécessite un identifiant unique. Sinon, vous ne pourrez pas les identifier, c'est aussi simple que cela.

Maintenant, comment vous allez le représenter, c'est une chose différente. Créer un objet avec les propriétés id et connection est un bon moyen de le faire (je le ferais sans hésiter). Vous pouvez également attacher le id directement à l'objet de connexion.

Rappelez-vous également que si vous souhaitez une communication entre utilisateurs, vous devez également envoyer l'identifiant de l'utilisateur cible, c'est-à-dire que si l'utilisateur A veut envoyer un message à l'utilisateur B, il est évident que A doit connaître l'identifiant de B.

63
freakish

Voici une messagerie privée/directe du serveur de discussion simple.

package.json

{
  "name": "chat-server",
  "version": "0.0.1",
  "description": "WebSocket chat server",
  "dependencies": {
    "ws": "0.4.x"
  }
}

server.js

var webSocketServer = new (require('ws')).Server({port: (process.env.PORT || 5000)}),
    webSockets = {} // userID: webSocket

// CONNECT /:userID
// wscat -c ws://localhost:5000/1
webSocketServer.on('connection', function (webSocket) {
  var userID = parseInt(webSocket.upgradeReq.url.substr(1), 10)
  webSockets[userID] = webSocket
  console.log('connected: ' + userID + ' in ' + Object.getOwnPropertyNames(webSockets))

  // Forward Message
  //
  // Receive               Example
  // [toUserID, text]      [2, "Hello, World!"]
  //
  // Send                  Example
  // [fromUserID, text]    [1, "Hello, World!"]
  webSocket.on('message', function(message) {
    console.log('received from ' + userID + ': ' + message)
    var messageArray = JSON.parse(message)
    var toUserWebSocket = webSockets[messageArray[0]]
    if (toUserWebSocket) {
      console.log('sent to ' + messageArray[0] + ': ' + JSON.stringify(messageArray))
      messageArray[0] = userID
      toUserWebSocket.send(JSON.stringify(messageArray))
    }
  })

  webSocket.on('close', function () {
    delete webSockets[userID]
    console.log('deleted: ' + userID)
  })
})

Instructions

Pour le tester, lancez npm install à installer ws . Ensuite, pour démarrer le serveur de discussion, exécutez node server.js (ou npm start) dans un onglet Terminal. Ensuite, dans un autre onglet Terminal, exécutez wscat -c ws://localhost:5000/1, où 1 est l'identifiant de l'utilisateur qui se connecte. Ensuite, dans un troisième onglet Terminal, exécutez wscat -c ws://localhost:5000/2, puis d'envoyer un message de l'utilisateur 2 à 1, entrer ["1", "Hello, World!"].

Des lacunes

Ce serveur de discussion est très simple.

  • Persistance

    Il ne stocke pas les messages dans une base de données, telle que PostgreSQL. Ainsi, l'utilisateur auquel vous envoyez un message doit être connecté au serveur pour le recevoir. Sinon, le message est perdu.

  • Sécurité

    C'est peu sûr.

    • Si je connais l'URL du serveur et l'ID utilisateur d'Alice, je peux imiter Alice, c'est-à-dire me connecter au serveur en tant que telle, me permettant de recevoir ses nouveaux messages entrants et de l'envoyer à tout utilisateur dont je connais également l'ID. Pour le rendre plus sécurisé, modifiez le serveur pour qu'il accepte votre jeton d'accès (au lieu de votre ID utilisateur) lors de la connexion. Ensuite, le serveur peut extraire votre ID utilisateur de votre jeton d’accès et vous authentifier.

    • Je ne sais pas s'il prend en charge WebSocket Secure (wss://) connexion puisque je ne l’ai testée que sur localhost, et je ne sais pas comment me connecter en toute sécurité à partir de localhost.

31
ma11hew28

Je voudrais partager ce que j'ai fait. J'espère que cela ne vous fait pas perdre votre temps.

J'ai créé une table de base de données contenant les champs ID, IP, nom d'utilisateur, logintime et logouttime. Quand un utilisateur se connecte, logintime sera corrigé unixtimestamp unix. Et lorsque la connexion est démarrée dans la base de données websocket, elle vérifie la plus grande durée d'exécution. Ce sera venu l'utilisateur connecté.

Et lorsque l'utilisateur se déconnecte, il stocke l'heure de déconnexion currect. L'utilisateur deviendra qui a quitté l'application.

Chaque fois qu'il y a un nouveau message, l'ID et l'IP de Websocket sont comparés et le nom d'utilisateur associé est affiché. Voici des exemples de code ...

// when a client connects
function wsOnOpen($clientID) {
      global $Server;
      $ip = long2ip( $Server->wsClients[$clientID][6] );

      require_once('config.php');
      require_once CLASSES . 'class.db.php';
      require_once CLASSES . 'class.log.php';

      $db = new database();
      $loga = new log($db);

      //Getting the last login person time and username
      $conditions = "WHERE which = 'login' ORDER BY id DESC LIMIT 0, 1";
      $logs = $loga->get_logs($conditions);
      foreach($logs as $rows) {

              $destination = $rows["user"];
              $idh = md5("$rows[user]".md5($rows["time"]));

              if ( $clientID > $rows["what"]) {
                      $conditions = "ip = '$ip', clientID = '$clientID'  

                      WHERE logintime = '$rows[time]'";
                      $loga->update_log($conditions);
             }
      }
      ...//rest of the things
} 
1
tashi