모든 사용자에게 메시지를 방송하기위한 코드를 작성했습니다 .
// 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조차 모릅니다. 보이는 것은 연결뿐입니다.
따라서 이제는 연결만으로 사용자를 저장해서는 안되며, 대신 userId
및 connection
개체를 포함 할 개체를 저장해야 합니다.
생각:
-
페이지로드가 완료되면 (DOM 준비)-Node.js 서버에 대한 연결을 설정합니다.
-
Node.js 서버가 연결을 수락하면 고유 한 문자열을 생성하여 클라이언트 브라우저로 보냅니다. 사용자 연결 및 고유 문자열을 개체에 저장합니다. 예 :
{UserID:"6", value: {connectionObject}}
-
클라이언트 측에서이 메시지가 도착하면 숨겨진 필드 또는 쿠키에 저장하십시오. (향후 NodeJs 서버에 대한 요청)
서버가 John에게 메시지를 보내려고 할 때 :
-
사전에서 john의 UserID를 찾아 해당 연결로 메시지를 보냅니다.
-
여기 (메시지 메커니즘에)에 등록 된 asp.net 서버 코드가 없습니다. NodeJ 만. *
질문:
이것이 올바른 방법입니까?
답변
이것은 올바른 방법 일뿐만 아니라 유일한 방법입니다. 기본적으로 각 연결에는 고유 한 ID가 필요합니다. 그렇지 않으면 그것들을 식별 할 수 없을 것입니다. 그것은 그렇게 간단합니다.
이제 그것을 어떻게 표현할지는 다른 것입니다. id
및 connection
속성을 사용 하여 개체를 만드는 것은 이를 수행하는 좋은 방법입니다 (확실히 갈 것입니다). 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를 요청 개체로 이동했으며 자세한 내용은 다음 링크를 확인할 수 있습니다.
답변
내가 한 일을 공유하고 싶습니다. 시간을 낭비하지 않기를 바랍니다.
필드 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를 사용하여 각 요소를 분리하는 것입니다 (자바 스크립트에서는 이러한 작업을 시도하지 않음). 친애하는,