私はallユーザーにメッセージをブロードキャストするためのコードを書きました:
使用コード:(簡単な説明)
// 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
に保存されます。目標:NodeJsサーバーがメッセージをspecificクライアント(John)に送信したいとします。
そしてここに質問があります:
NodeJsサーバーは、Johnがどの接続を持っているかをどのようにして知るのでしょうか?
NodeJsサーバーはJohnさえも知りません。表示されるのは接続のみです。
だから、今では、接続だけでユーザーを保存するべきではなく、代わりに、userId
とconnection
オブジェクト。
そして、ここに私のアイデアがあります:
ページの読み込みが完了したら(Dom ready)-NodeJsサーバーへの接続を確立します。
NodeJsサーバーが接続を受け入れる場合-一意の文字列を生成し、クライアントブラウザーに送信します。ユーザー接続と一意の文字列をオブジェクトに保存します。 例{UserID:"6" , value :{connectionObject}}
クライアント側で、このメッセージが到着したら-隠しフィールドまたはCookieに保存します。 (NodeJsサーバーへの将来のリクエスト用)
サーバーがJohnにメッセージを送信する場合:
(メッセージメカニズム内に)ここに含まれる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
をインストールします。その後、チャットサーバーを起動するには、1つの[ターミナル]タブでnode server.js
(またはnpm start
)を実行します。次に、別の[ターミナル]タブで、wscat -c ws://localhost:5000/1
を実行します。1
は接続ユーザーのユーザーIDです。次に、3番目の[ターミナル]タブでwscat -c ws://localhost:5000/2
を実行し、ユーザー2
から1
にメッセージを送信するには、["1", "Hello, World!"]
と入力します。
このチャットサーバーは非常にシンプルです。
持続性
PostgreSQLなどのデータベースにはメッセージを保存しません。そのため、メッセージを送信するユーザーは、サーバーに接続してメッセージを受信する必要があります。そうしないと、メッセージは失われます。
セキュリティ
安全ではありません。
サーバーのURLとAliceのユーザーIDがわかっている場合は、Aliceになりすますことができます。つまり、Aliceとしてサーバーに接続し、新しい着信メッセージを受信して、ユーザーIDを知っているユーザーにメッセージを送信できるようにします。より安全にするには、接続時に(ユーザーIDではなく)アクセストークンを受け入れるようにサーバーを変更します。その後、サーバーはアクセストークンからユーザーIDを取得し、ユーザーを認証できます。
localhost
でしかテストしていないため、WebSocket Secure(wss://
)接続をサポートしているかどうかはわかりません。また、localhost
から安全に接続する方法もわかりません。
私がやったことを共有したいと思います。時間を無駄にしないことを願っています。
フィールドID、IP、ユーザー名、ログイン時間、ログアウト時間を保持するデータベーステーブルを作成しました。ユーザーがログインすると、logintimeは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を作成し、各ディスペンサーがWebSocketを簡単に作成し、スレッドの問題なしで使用できるようにします(特定の関数を呼び出します) GetSettingsやRequestTicketなどのWebSocketで)。あなたの例の違いは、配列の代わりにConcurrentDictionaryを使用して各要素を分離することです(javascriptでそのようなことをしようとしたことはありません)。宜しくお願いします、