সকেট.ইও এবং নোড.জেএস সহ নির্দিষ্ট ক্লায়েন্টকে বার্তা প্রেরণ করুন


189

আমি সকেট.ইও এবং নোড.জেএস এর সাথে কাজ করছি এবং এখন অবধি এটি বেশ ভাল মনে হচ্ছে তবে সার্ভার থেকে কোনও নির্দিষ্ট ক্লায়েন্টকে কীভাবে কোনও বার্তা পাঠানো যায় তা আমি জানি না, এরকম কিছু:

client.send(message, receiverSessionId)

কিন্তু তন্ন তন্ন .send()না .broadcast()পদ্ধতি আমার প্রয়োজন সরবরাহ বলে মনে হচ্ছে।

আমি একটি সম্ভাব্য সমাধান হিসাবে যা পেয়েছি, তা হ'ল .broadcast()পদ্ধতিটি দ্বিতীয় পরামিতি হিসাবে সেশনআইডসের একটি অ্যারে গ্রহণ করে যা বার্তাটি প্রেরণ করে না, তাই আমি সেই মুহূর্তে সার্ভারের সাথে সংযুক্ত সমস্ত সেশনআইডের সাথে একটি অ্যারে পাস করতে পারি, এটি ব্যতীত আমি বার্তাটি প্রেরণ করতে চাই, তবে আমি মনে করি এর থেকে আরও ভাল সমাধান অবশ্যই পাওয়া উচিত।

কোন ধারনা?

উত্তর:


95

ওয়েল আপনাকে সেই (আশ্চর্য) জন্য ক্লায়েন্টকে ধরে ফেলতে হবে, আপনি হয় সহজ উপায়ে যেতে পারেন:

var io = io.listen(server);
io.clients[sessionID].send()

যা ভেঙে যেতে পারে, আমি সন্দেহ করি, তবে এটি সর্বদা এমন একটি সম্ভাবনা যা io.clientsপরিবর্তিত হতে পারে তাই সাবধানতার সাথে উপরেরটি ব্যবহার করুন

অথবা আপনি নিজেরাই ক্লায়েন্টদের খোঁজ রাখেন, তাই আপনি এগুলি শ্রোতার clientsমধ্যে আপনার নিজের বস্তুর সাথে যুক্ত করে connectionশ্রোতার মধ্যে সরিয়ে দিন disconnect

আমি পরেরটিটি ব্যবহার করব, যেহেতু আপনার আবেদনের উপর নির্ভর করে আপনি যেভাবেই ক্লায়েন্টদের উপর আরও বেশি অবস্থান রাখতে চান, তাই এর মতো কিছু clients[id] = {conn: clientConnect, data: {...}}কাজ করতে পারে।


6
তবে, আপনি আরও একটি সম্পূর্ণ উদাহরণের দিকে নির্দেশ করতে পারেন বা কিছুটা বিস্তৃত করতে পারেন? আমি এই পদ্ধতিটি বুঝতে আগ্রহী, তবে আমি নিশ্চিত নই যে আপনি এই উদাহরণটিতে ব্যবহার করছেন এমন ভেরিয়েবল / অবজেক্টগুলিকে আমি চিনতে পারি। ক্লায়েন্টগুলিতে [আইডি] = {সংযোগ: ক্লায়েন্ট সংযোগ, ডেটা: {...}}, ক্লায়েন্টগুলি [আইডি] উপরে আইওএক্লিয়েন্টস [সেশনআইডি] তে দেখা আইও অবজেক্টের অংশ? এছাড়াও ক্লায়েন্ট কানেক্ট সংযোগটি কী? ধন্যবাদ।
অ্যান্ড্রুহেন্ডারসন

@ আইভো-ভিটজেল হাই, আপনি কি আমাকে এই বিষয়ে ইয়োলো করতে পারেন? stackoverflow.com/questions/38817680/...
মাহদি pishguy

178

আইভো ওয়েটজেলের উত্তর সকেট.ইও 0.9-তে বৈধ বলে মনে হচ্ছে না।

সংক্ষেপে আপনাকে এখন সংরক্ষণ করতে হবে socket.idএবং এতে io.sockets.socket(savedSocketId).emit(...) বার্তা প্রেরণের জন্য ব্যবহার করতে হবে।

এইভাবে ক্লাস্টারড নোড.জেএস সার্ভারে এই কাজটি পেয়েছিলাম:

প্রথমে আপনাকে রেডিস স্টোরটিকে স্টোর হিসাবে সেট করতে হবে যাতে বার্তা ক্রস প্রসেসে যেতে পারে:

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


4
ধন্যবাদ এটি সহায়ক ছিল। পরিবর্তে আমাকে কেবল একটি অ্যারে ব্যবহার করতে হয়েছিল: io.of('/mynamespace').sockets[socketID].emit(...)(এটির কারণটি আমি জানি না যে আমি একটি নেমস্পেস ব্যবহার করছি)
অ্যাড্রিয়েন শুলার

ক্লাস্টারযুক্ত পরিবেশে, আমি কীভাবে নিশ্চিত করব যে সকেটের সঠিক প্রক্রিয়াটি মেসেজ পাঠাচ্ছে?
গাল বেন-হাইম

এনজিআইএনএক্স বা এইচপিপ্রक्सी @ গাল বেন-হাইমের সৌজন্যে কীভাবে?
ম্যাটানস্টার

var হোল্ডার = নতুন সোকেটিও.রিডিস স্টোর; ^ TypeError: অপরিজ্ঞাতটি অবজেক্টে কোনও ফাংশন নয় <<বেনামে> (সি: \ ব্যবহারকারীগণ দেব \ ডেস্কটপ out নটি-সার্ভার \ সার্ভার.js: 108: 14) এ মডিউল._কম্পাইল (মডিউল.js: 460: 26) এ অবজেক্ট.মডিউল._ এক্সটেনশনস..জেএস (মডিউল.জেএস: 478: 10) ফাংশন.মোডুল.এলডে (মডিউল.জেএস: 310: 12) ফাংশন.মোডুলে। রানডমেন (মডিউল.জেএস: 501: 10) স্টার্টআপে (নোড.জেএস: 129: 16) নোড.জেজে: 814: 3
লুকাস বার্তোলো

1
io.sockets.socket(socket_id)Socket.io 1.0 এ সরানো হয়েছে। github.com/socketio/sket.io/issues/1618#issuecomment-46151246
ইমমাথন

97

প্রতিটি সকেট একটি নামের জন্য সকেট আইডি সহ একটি রুমে যোগ দেয়, যাতে আপনি ঠিক করতে পারেন

io.to(socket#id).emit('hey')

দস্তাবেজ: http://sket.io/docs/rooms-and-namespaces/#default-room

চিয়ার্স


7
এটি সর্বাধিক উত্তর এবং ডাব্লু / সকেট.ইওর নতুন সংস্করণে কাজ করে। সেখানে একটা চমৎকার ঠকাই শীট এখানে দেওয়া হল: stackoverflow.com/questions/10058226/...
blented

4
নোট করুন যে এটি একটি ইভেন্ট সম্প্রচারের একটি 'সম্প্রচার' প্রকার। সুতরাং আপনি যদি এইটিতে একটি কলব্যাক সেট করার চেষ্টা করেন তবে আপনার একটি ত্রুটি হবে। যদি আপনাকে কলব্যাক সহ কোনও নির্দিষ্ট সকেটে কোনও ইভেন্ট পাঠাতে হয় তবে @ পিএইচপিথিংকিংয়ের উত্তর এবং ব্যবহার করুন io.sockets.connected[socketid].emit();। 1.4.6 দিয়ে পরীক্ষা করা হয়েছে।
tbutcaru

তবে আমি এই ত্রুটিটি পেয়েছি: io.to ["JgCoFX9AiCND_ZhdAAAC"] e ^ TypeError: অপরিজ্ঞাতকৃত সম্পত্তি 'নির্গমন' পড়তে পারে না
রাজা

85

সবচেয়ে সহজ, সবচেয়ে মার্জিত সমাধান

এটি এতটা সহজ:

client.emit("your message");

এবং এটাই.

কিন্তু কিভাবে? আমাকে একটি উদাহরণ দাও

আমাদের সবার যা প্রয়োজন তা হ'ল একটি সম্পূর্ণ উদাহরণ এবং এরপরে এটিই ঘটে। এটি সর্বশেষতম সকেট.আইও সংস্করণ (২.০.৩) দিয়ে পরীক্ষা করা হয়েছে এবং এটি আধুনিক জাভাস্ক্রিপ্টও ব্যবহার করছে (যা আমাদের এখনই ব্যবহার করা উচিত)।

উদাহরণটি দুটি অংশ নিয়ে গঠিত: একটি সার্ভার এবং একটি ক্লায়েন্ট। যখনই কোনও ক্লায়েন্ট সংযুক্ত হয়, এটি সার্ভার থেকে একটি পর্যায়ক্রমিক ক্রম নম্বর পাওয়া শুরু করে। প্রতিটি নতুন ক্লায়েন্টের জন্য একটি নতুন ক্রম শুরু হয়, তাই সার্ভারকে স্বতন্ত্রভাবে সেগুলি ট্র্যাক করে রাখতে হবে keep সেখানেই "" আমাকে একটি নির্দিষ্ট ক্লায়েন্টের কাছে একটি বার্তা প্রেরণ করা দরকার " খেলতে আসে। কোডটি বুঝতে খুব সহজ। চলো এটা দেখি.

সার্ভার

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

আমি এখানে পূর্ণ কোড সহ একটি সংক্ষিপ্তসারও প্রস্তুত করেছি ।


8000 বন্দরটি কি উত্পাদনের ক্ষেত্রে সোকেটিওর আদর্শ?
লাল

1
দুঃখিত, আমি উত্তর দেওয়ার জন্য এত দীর্ঘ সময় নিয়েছি, @ ইঙ্গো। ওয়েবোকেট বা এইচটিটিপি সার্ভার উভয়ই পরীক্ষা করার সময় নোড সম্প্রদায় 8000 হ'ল একটি সাধারণ বন্দর (3000 এছাড়াও সাধারণ)। অবশ্যই আপনি এটি উত্পাদনে ব্যবহার করতে পারেন, তবে আমি নিশ্চিত না যে এটি কতটা সাধারণ is তবে যাইহোক, আপনি যে কোনও বন্দরটি ব্যবহার করতে পারবেন যতক্ষণ না আপনার গেটওয়ে / লোড ব্যালেন্সার / ইত্যাদি তার জন্য প্রস্তুত থাকে।
লুসিও পাইভা

আমি পাইথন / পিএইচপি প্রোগ্রামার এবং আমি সকেট এবং নোডে নতুন আছি, প্রশ্নটি হল কেন আমাদের প্রতিটি সেকেন্ডে একই ব্যবহারকারীর সিক সংখ্যা বাড়ানো দরকার? এটা কি শুধু ডেমো জন্য?
উমাইর

1
@ উমির এটি কেবল ডেমো উদ্দেশ্যে, একটি ক্রম সংখ্যা বাড়ানোর কোনও সত্যিকারের প্রয়োজন নেই। এটি কেবল এটি দেখানোর জন্য যে আপনি প্রতিটি ক্লায়েন্টকে স্টাফ প্রেরণ চালিয়ে যেতে পারেন এবং তারা এটি গ্রহণ করবে।
লুসিও পাইভা

আমি এই উদাহরণে দেখছি না যে কীভাবে একটি নির্দিষ্ট ক্লায়েন্ট কেবল এবং কেবলমাত্র অন্য ক্লায়েন্টকে একটি বার্তা প্রেরণ করে। প্রতিটি ক্লায়েন্ট কেবলমাত্র নিজের ক্রম নম্বরটি জানেন যেমন আপনি এটি ডেমোর জন্য রেখেছেন এবং তৈরি করেছেন এবং এই সিকোয়েন্স নম্বরগুলি থেকে কোনও সকেট আইডিতে কোনও মানচিত্র নেই যা সেই সকেট আইডি সহ ক্লায়েন্টকে সরাসরি একটি বার্তা প্রেরণের জন্য প্রয়োজন।
সেলুক 14

35

তুমি ব্যবহার করতে পার

// কেবল প্রেরক-ক্লায়েন্টকে বার্তা প্রেরণ করুন

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');


আমার জন্য কাজ করে, আমাকে "কনস্ট সকেট = প্রয়োজন ('সকেট.ইও')) (HTTP) যোগ করতে হয়েছিল;" আমার সার্ভার.জেএস ফাইল এ।
আইপিজার্ড 21'6

35

1.0 এ আপনার ব্যবহার করা উচিত:

io.sockets.connected[socketid].emit();

1
হ্যাঁ! Io.sockets.connected কাজগুলিতে পরিবর্তন করা হচ্ছে।
Fraggle

যাঁরা টাইপস্ক্রিপ্ট ব্যবহার করছেন, টাইপিং অনুযায়ী এটি বর্তমানে এটির জন্য 'ক্যানোনিকাল' এপিআই।
আভি চেরি

তবে আমি একটি ত্রুটি পেয়েছি: io.sockets.connected ["JgCoFX9AiCND_ZhdAAAC"]। এমিড ("সকেটফ্রম সার্ভার", তথ্য); ^ প্রকারের ত্রুটি: পূর্বনির্ধারিত সম্পত্তি 'নির্গমন' পড়তে পারে না
রাজা

এটি সম্ভবত এপিআই আপডেট হয়েছে এবং এর মতো কোনও বস্তু io.sockets.connected["something"]এবং এর emitপদ্ধতি নেই বলেই সম্ভবত এটি ঘটে ।
সেলুকুক

12

আমরা যে সংস্করণটি ব্যবহার করছি তা যদি আমরা কেবল কনসোল.লগ () "সার্ভারের সাইড নোডেজ কোডে" আইও "অবজেক্টটি ব্যবহার করি, [উদাহরণস্বরূপ io.on ('সংযোগ', ফাংশন (সকেট) {...});] , আমরা দেখতে পাচ্ছি যে "আইও" হ'ল একটি জসন বস্তু এবং অনেকগুলি শিশু অবজেক্ট রয়েছে যেখানে সকেট আইডি এবং সকেট অবজেক্টগুলি সঞ্চয় করা হয়।

আমি সকেট.ইও সংস্করণটি 1.3.5, বিটিডাব্লু ব্যবহার করছি।

আমরা যদি আইও অবজেক্টে দেখি তবে এতে রয়েছে,

 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 টির মধ্যে যে কোনও একটিতে আমাদের লক্ষ্য অর্জন করতে পারি,

  1. io.sockets.connected [socketid] .emit (); অথবা
  2. io.eio.clients [socketid] .emit (); অথবা
  3. io.engine.clients [socketid] .emit ();

তবে আমি এই ত্রুটিটি পেয়েছি: io.eio.clients ["JgCoFX9AiCND_ZhdAAAC"] e ^ TypeError: অপরিজ্ঞাতকৃত সম্পত্তি 'নির্গমন' পড়তে পারে না
রাজা

বর্তমানে (২.১.১ সংস্করণ সহ) এটি কেবল সকেটস কানেক্টেড জন্য কাজ করেছে, তবে অন্য দুটি নয়।
জেমস

10

তুমি এটি করতে পারো

সার্ভারে।

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

7

সংস্করণ 1.4.5 হিসাবে, আপনি io.to () এ সঠিকভাবে উপসর্গযুক্ত সকেট সরবরাহ করেছেন তা নিশ্চিত হন। আমি সকেটটি নিচ্ছিলাম ক্লায়েন্টটি ডিবাগ করার জন্য লগ হয়েছে এবং এটি উপসর্গ ছাড়াই ছিল তাই আমি খুঁজে না পাওয়া পর্যন্ত চিরতরে অনুসন্ধান শেষ করেছি! সুতরাং আপনার যদি আইডিটি পূর্বনির্ধারণ না করা থাকে তবে আপনাকে এটি এটি করতে হতে পারে:

io.to('/#' + socketId).emit('myevent', {foo: 'bar'});

6

io.sockets.sockets [socket.id] .emit (...) v0.9 এ আমার জন্য কাজ করেছে


স্ট্যাক ওভারফ্লোতে আপনাকে স্বাগতম। এই উত্তরটি বিদ্যমান উত্তরের সাথে খুব বেশি সম্পর্কিত বলে মনে হচ্ছে না। আপনার আরও খ্যাতি পাওয়ার পরে আপনি অন্য ব্যক্তির পোস্টগুলিতে মন্তব্য করতে সক্ষম হবেন । এটি একটি মন্তব্যের জন্য আরও উপযুক্ত seems
জেরি

2

এছাড়াও আপনি ক্লায়েন্টদের রেফারেন্স রাখতে পারেন। তবে এটি আপনার স্মরণকে ব্যস্ত করে তোলে।

একটি খালি অবজেক্ট তৈরি করুন এবং এতে আপনার ক্লায়েন্টদের সেট করুন।

const myClientList = {};

  server.on("connection", (socket) => {
    console.info(`Client connected [id=${socket.id}]`);
     myClientList[socket.id] = socket;   
  });
  socket.on("disconnect", (socket) => {
    delete myClientList[socket.id];
  });

তারপরে অবজেক্ট থেকে আইডি দিয়ে আপনার নির্দিষ্ট ক্লায়েন্টকে কল করুন

myClientList[specificId].emit("blabla","somedata");

0

সকেট.আইও আপনাকে আপনার সকেটগুলিকে "নেমস্পেস" করতে দেয়, যার অর্থ মূলত বিভিন্ন প্রান্ত বা পথ নির্ধারণ করা।

এটি সহায়তা করতে পারে: http://sket.io/docs/rooms-and-namespaces/

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.