[javascript] webSocket을 사용하여 특정 연결된 사용자에게 메시지를 보내 시나요?

모든 사용자에게 메시지를 방송하기위한 코드를 작성했습니다 .

// 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;
...

주의하십시오 :

  • 사용자 참조가 없지만 연결 만 있습니다.
  • 모든 사용자 연결은 array.

목표 : Node.js 서버가 특정 클라이언트 (John)에게 메시지를 보내려고한다고 가정 해 보겠습니다. NodeJs 서버는 John이 어떤 연결을 가지고 있는지 어떻게 알 수 있습니까? Node.js 서버는 John조차 모릅니다. 보이는 것은 연결뿐입니다.

따라서 이제는 연결만으로 사용자를 저장해서는 안되며, 대신 userIdconnection개체를 포함 할 개체를 저장해야 합니다.

생각:

  • 페이지로드가 완료되면 (DOM 준비)-Node.js 서버에 대한 연결을 설정합니다.

  • Node.js 서버가 연결을 수락하면 고유 한 문자열을 생성하여 클라이언트 브라우저로 보냅니다. 사용자 연결 및 고유 문자열을 개체에 저장합니다. 예 :{UserID:"6", value: {connectionObject}}

  • 클라이언트 측에서이 메시지가 도착하면 숨겨진 필드 또는 쿠키에 저장하십시오. (향후 NodeJs 서버에 대한 요청)


서버가 John에게 메시지를 보내려고 할 때 :

  • 사전에서 john의 UserID를 찾아 해당 연결로 메시지를 보냅니다.

  • 여기 (메시지 메커니즘에)에 등록 된 asp.net 서버 코드가 없습니다. NodeJ 만. *

질문:

이것이 올바른 방법입니까?



답변

이것은 올바른 방법 일뿐만 아니라 유일한 방법입니다. 기본적으로 각 연결에는 고유 한 ID가 필요합니다. 그렇지 않으면 그것들을 식별 할 수 없을 것입니다. 그것은 그렇게 간단합니다.

이제 그것을 어떻게 표현할지는 다른 것입니다. idconnection속성을 사용 하여 개체를 만드는 것은 이를 수행하는 좋은 방법입니다 (확실히 갈 것입니다). id연결 개체에 직접 연결할 수도 있습니다 .

또한 사용자 간의 통신을 원할 경우 대상 사용자의 ID도 전송해야합니다. 즉, 사용자 A가 사용자 B에게 메시지를 보내고 싶을 때 A는 B의 ID를 알아야합니다.


답변

다음은 간단한 채팅 서버 비공개 / 직접 메시징입니다.

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)
  })
})

명령

테스트하려면 실행 npm install하여 ws. 그런 다음 채팅 서버를 시작하려면 하나의 터미널 탭에서 실행 node server.js(또는 npm start)합니다. 그런 다음 다른 터미널 탭에서을 실행합니다 wscat -c ws://localhost:5000/1. 여기서는 1연결하는 사용자의 사용자 ID입니다. 그런 다음 세 번째 터미널 탭에서을 실행 wscat -c ws://localhost:5000/2한 다음 사용자로부터에 메시지를 보내 2려면 1을 입력 ["1", "Hello, World!"]합니다.

단점

이 채팅 서버는 매우 간단합니다.

  • 고집

    PostgreSQL과 같은 데이터베이스에 메시지를 저장하지 않습니다. 따라서 메시지를 보내는 사용자는 메시지를 수신하기 위해 서버에 연결되어 있어야합니다. 그렇지 않으면 메시지가 손실됩니다.

  • 보안

    안전하지 않습니다.

    • 서버의 URL과 Alice의 사용자 ID를 알고 있으면 Alice를 가장 할 수 있습니다. 즉, Alice로 서버에 연결하여 그녀의 새 수신 메시지를 수신하고 그녀의 메시지를 내가 아는 사용자 ID를 가진 모든 사용자에게 보낼 수 있습니다. 보안을 강화하려면 연결할 때 사용자 ID 대신 액세스 토큰을 허용하도록 서버를 수정하십시오. 그러면 서버는 액세스 토큰에서 사용자 ID를 가져와 인증 할 수 있습니다.

    • WebSocket Secure ( wss://) 연결을 지원하는지 확실하지 않습니다. 에서만 테스트했기 때문에에서 localhost안전하게 연결하는 방법도 모르겠습니다 localhost.


답변

사용하는 사람의 경우 ws버전 3 이상을. @ ma11hew28에서 제공하는 답변을 사용하려면이 블록을 다음과 같이 변경하면됩니다.

webSocketServer.on('connection', function (webSocket) {
  var userID = parseInt(webSocket.upgradeReq.url.substr(1), 10)
webSocketServer.on('connection', function (webSocket, req) {
  var userID = parseInt(req.url.substr(1), 10)

ws 패키지가 upgradeReq를 요청 개체로 이동했으며 자세한 내용은 다음 링크를 확인할 수 있습니다.

참조 : https://github.com/websockets/ws/issues/1114


답변

내가 한 일을 공유하고 싶습니다. 시간을 낭비하지 않기를 바랍니다.

필드 ID, IP, 사용자 이름, 로그인 시간 및 로그 아웃 시간을 포함하는 데이터베이스 테이블을 만들었습니다. 사용자가 로그인 할 때 로그인 시간은 현재 unixtimestamp unix입니다. 그리고 websocket 데이터베이스에서 연결이 시작되면 가장 큰 로그인 시간을 확인합니다. 사용자가 로그인 한 상태가됩니다.

그리고 사용자가 로그 아웃하면 현재 로그 아웃 시간이 저장됩니다. 사용자는 앱을 떠난 사람이됩니다.

새 메시지가있을 때마다 Websocket ID와 IP를 비교하여 관련 사용자 이름이 표시됩니다. 다음은 샘플 코드입니다 …

// 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
}


답변

흥미로운 게시물 (내가하는 일과 유사). 디스펜서를 WebSocket과 연결하는 API (C #)를 만들고 있습니다. 각 디스펜서에 대해 WebSocket과 DispenserId를 저장하는 ConcurrentDictionary를 생성하여 각 Dispenser가 WebSocket을 쉽게 생성하고 나중에 스레드 문제없이 사용할 수 있도록합니다 (특정 함수 호출). GetSettings 또는 RequestTicket과 같은 WebSocket에서). 예제의 차이점은 배열 대신 ConcurrentDictionary를 사용하여 각 요소를 분리하는 것입니다 (자바 스크립트에서는 이러한 작업을 시도하지 않음). 친애하는,


답변