私は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(...)
を使用してメッセージを送信する必要があります。
これは、クラスター化された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')
docs: 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] },
ここでsocketids "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つの方法のいずれかで目標を達成できると思います。
あなたはこれを行うことができます
サーバー上。
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)
})
バージョン1.4.5の時点で、io.to()で適切にプレフィックスされたsocketIdを提供していることを確認してください。私はクライアントがデバッグするためにログに記録したsocketIdを使用していましたが、プレフィックスがなかったため、最終的に検索することになりました!したがって、所有しているIDに接頭辞が付いていない場合は、次のようにする必要があります。
io.to('/#' + socketId).emit('myevent', {foo: 'bar'});
io.sockets.sockets [socket.id] .emit(...)はv0.9で機能しました
Socket.IOでは、ソケットを「名前空間」にすることができます。これは、本質的には、異なるエンドポイントまたはパスを割り当てることを意味します。
これは役立つかもしれません: http://socket.io/docs/rooms-and-namespaces/