socket.ioとnode.jsを使用して特定のクライアントにメッセージを送信します
-
09-10-2019 - |
質問
私はsocket.ioとnode.jsを使って作業していますが、今のところかなりうまくいっているように見えますが、次のようなメッセージをサーバーから特定のクライアントに送信する方法がわかりません。
client.send(message, receiverSessionId)
しかし、どちらも .send()
も .broadcast()
メソッドは私のニーズを満たしているようです。
考えられる解決策として私が見つけたのは、 .broadcast()
このメソッドは、メッセージを送信しないSessionIdの配列を2番目のパラメータとして受け入れるため、メッセージを送信したいものを除く、その時点で接続されているすべてのSessionIdを含む配列をサーバーに渡すことができますが、必要があると感じますより良い解決策を。
何か案は?
解決
まあ、あなたはそのためにクライアントをつかまなければなりません(驚き)、あなたは簡単な方法を行くことができます:
var io = io.listen(server);
io.clients[sessionID].send()
それは壊れるかもしれません、私はそれを疑いますが、それは常に可能性です io.clients
変更される可能性があるので、上記を注意して使用してください
または、あなたは自分でクライアントを追跡するので、あなたはそれらを自分のものに追加します clients
のオブジェクト connection
リスナーとそれらを削除します disconnect
リスナー。
私は後者を使用します。あなたのアプリケーションに応じて、とにかくクライアントにより多くの状態を持っているかもしれないので、 clients[id] = {conn: clientConnect, data: {...}}
仕事をするかもしれません。
他のヒント
Ivo Wetzelの答えは、Socket.io 0.9ではもう有効ではないようです。
要するに、あなたは今保存する必要があります socket.id
そして使用します io.sockets.socket(savedSocketId).emit(...)
メッセージを送信します。
これは、Clustered node.jsサーバーでこれを機能させた方法です。
まず、メッセージがクロスプロセスに移行できるように、Redisストアをストアとして設定する必要があります。
var express = require("express");
var redis = require("redis");
var sio = require("socket.io");
var client = redis.createClient()
var app = express.createServer();
var io = sio.listen(app);
io.set("store", new sio.RedisStore);
// In this example we have one master client socket
// that receives messages from others.
io.sockets.on('connection', function(socket) {
// Promote this socket as master
socket.on("I'm the master", function() {
// Save the socket id to Redis so that all processes can access it.
client.set("mastersocket", socket.id, function(err) {
if (err) throw err;
console.log("Master socket is now" + socket.id);
});
});
socket.on("message to master", function(msg) {
// Fetch the socket id from Redis
client.get("mastersocket", function(err, socketId) {
if (err) throw err;
io.sockets.socket(socketId).emit(msg);
});
});
});
ここでクラスタリングコードを省略しました。なぜなら、これをより乱雑にしているからですが、追加するのは些細なことです。すべてをワーカーコードに追加するだけです。ここでより多くのドキュメント http://nodejs.org/api/cluster.html
各ソケットは、名前のソケットIDを備えた部屋に参加するので、ただ
io.to(socket#id).emit('hey')
ドキュメント: http://socket.io/docs/rooms-and-namespaces/#default-room
乾杯
最もシンプルでエレガントなソリューション
それは次のように簡単です。
client.emit("your message");
以上です。
しかし、どうやって?例を挙げてください
私たち全員が必要としているのは、実際には完全な例であり、それが次に続きます。これは最新のsocket.ioバージョン(2.0.3)でテストされており、最新のJavaScriptも使用されています(今では誰もが使用しているはずです)。
この例は 2 つの部分で構成されています。サーバーとクライアント。クライアントが接続するたびに、サーバーから定期的なシーケンス番号の受信が開始されます。新しいシーケンスは新しいクライアントごとに開始されるため、サーバーはそれらを個別に追跡する必要があります。そこで、 「特定のクライアントにメッセージを送信する必要がある」 が登場します。コードは非常に簡単に理解できます。それを見てみましょう。
サーバ
server.js
const
io = require("socket.io"),
server = io.listen(8000);
let
sequenceNumberByClient = new Map();
// event fired every time a new client connects:
server.on("connection", (socket) => {
console.info(`Client connected [id=${socket.id}]`);
// initialize this client's sequence number
sequenceNumberByClient.set(socket, 1);
// when socket disconnects, remove it from the list:
socket.on("disconnect", () => {
sequenceNumberByClient.delete(socket);
console.info(`Client gone [id=${socket.id}]`);
});
});
// sends each client its current sequence number
setInterval(() => {
for (const [client, sequenceNumber] of sequenceNumberByClient.entries()) {
client.emit("seq-num", sequenceNumber);
sequenceNumberByClient.set(client, sequenceNumber + 1);
}
}, 1000);
サーバーはポート 8000 で受信接続の待機を開始します。新しいクライアントが到着すると、そのシーケンス番号を追跡できるようにその新しいクライアントをマップに追加します。また、そのクライアントの意見も聞きます。 disconnect
イベント、マップから削除されるとき。
毎秒タイマーが起動されます。その際、サーバーはマップ内を調べ、現在のシーケンス番号を含むメッセージをすべてのクライアントに送信します。次に、それをインクリメントし、その数値をマップに再度保存します。以上です。簡単にピーシー。
クライアント
クライアント部分はさらにシンプルです。サーバーに接続して、 seq-num
メッセージが到着するたびにコンソールに出力されます。
client.js
const
io = require("socket.io-client"),
ioClient = io.connect("http://localhost:8000");
ioClient.on("seq-num", (msg) => console.info(msg));
サンプルの実行
必要なライブラリをインストールします。
npm install socket.io
npm install socket.io-client
サーバーを実行します。
node server
他のターミナル ウィンドウを開き、次のコマンドを実行して必要なだけクライアントを生成します。
node client
完全なコードを含む要点も用意しました ここ.
1.0で使用する必要があります。
io.sockets.connected[socketid].emit();
使用できます
//送信者クライアントにのみメッセージを送信します
socket.emit('message', 'check this');
//または送信者を含むすべてのリスナーに送ることができます
io.emit('message', 'check this');
//送信者を除くすべてのリスナーに送信します
socket.broadcast.emit('message', 'this is a message');
//またはあなたはそれを部屋に送ることができます
socket.broadcast.to('chatroom').emit('message', 'this is the message to all');
サーバーサイドnodeJSコードで使用する「io」オブジェクトをconsole.log()のみを使用している場合は何であれ、[io.on( 'connection'、function(socket){...});] 、「IO」は単なるJSONオブジェクトであり、ソケットIDとソケットオブジェクトが保存される多くの子オブジェクトがあることがわかります。
socket.ioバージョン1.3.5、ところで。
IOオブジェクトを見ると、
sockets:
{ name: '/',
server: [Circular],
sockets: [ [Object], [Object] ],
connected:
{ B5AC9w0sYmOGWe4fAAAA: [Object],
'hWzf97fmU-TIwwzWAAAB': [Object] },
ここでは、ソケット "b5ac9w0symogwe4faaaa"などを見ることができます。
io.sockets.connected[socketid].emit();
繰り返しますが、さらに検査すると、次のようなセグメントを見ることができます。
eio:
{ clients:
{ B5AC9w0sYmOGWe4fAAAA: [Object],
'hWzf97fmU-TIwwzWAAAB': [Object] },
だから、私たちはここからソケットを取得することができます
io.eio.clients[socketid].emit();
また、エンジンの下に私たちは持っています、
engine:
{ clients:
{ B5AC9w0sYmOGWe4fAAAA: [Object],
'hWzf97fmU-TIwwzWAAAB': [Object] },
だから、私たちも書くことができます、
io.engine.clients[socketid].emit();
ですから、上記の3つの方法のいずれかで目標を達成できると思います。
- io.sockets.connected [socketid] .emit();また
- io.eio.clients [socketid] .emit();また
- io.engine.clients [socketid] .emit();
あなたはこれを行うことができます
サーバー上。
global.io=require("socket.io")(server);
io.on("connection",function(client){
console.log("client is ",client.id);
//This is handle by current connected client
client.emit('messages',{hello:'world'})
//This is handle by every client
io.sockets.emit("data",{data:"This is handle by every client"})
app1.saveSession(client.id)
client.on("disconnect",function(){
app1.deleteSession(client.id)
console.log("client disconnected",client.id);
})
})
//And this is handle by particular client
var socketId=req.query.id
if(io.sockets.connected[socketId]!=null) {
io.sockets.connected[socketId].emit('particular User', {data: "Event response by particular user "});
}
また、クライアントでは、非常に簡単に処理できます。
var socket=io.connect("http://localhost:8080/")
socket.on("messages",function(data){
console.log("message is ",data);
//alert(data)
})
socket.on("data",function(data){
console.log("data is ",data);
//alert(data)
})
socket.on("particular User",function(data){
console.log("data from server ",data);
//alert(data)
})
io.sockets.sockets [socket.id] .emit(...)はv0.9で私のために働きました
バージョン1.4.5の時点で、io.to()で適切にプレフィックスされたソケットを提供してください。クライアントがデバッグにログインしたソケットを使用していましたが、プレフィックスがなかったので、わかるまで永遠に検索しました!したがって、あなたが持っているIDがプレフィックスされていない場合、あなたはこのようにそれをする必要があるかもしれません:
io.to('/#' + socketId).emit('myevent', {foo: 'bar'});
socket.ioでは、ソケットを「名前を付けて」「名前を付けて」ます。これは、本質的に異なるエンドポイントまたはパスを割り当てることを意味します。
これは役立つかもしれません:http://socket.io/docs/rooms-and-namespaces/