Cara mengirim pesan ke klien tertentu dengan socket.io

96

Saya mulai dengan socket.io + node.js, saya tahu cara mengirim pesan secara lokal dan menyiarkan socket.broadcast.emit()fungsi: - semua klien yang terhubung menerima pesan yang sama.

Sekarang, saya ingin tahu cara mengirim pesan pribadi ke klien tertentu, maksud saya satu soket untuk obrolan pribadi antara 2 orang (aliran Klien-ke-Klien). Terima kasih.

Nizar B.
sumber
Maaf psiphi75 tapi link ini tidak menjawab jawaban saya, bukan pertanyaan duplikat.
Nizar B.
1
@ psiphi75, ini bukan duplikat
softvar
1
Tidak tahan orang seperti @psiphi. Apakah Anda seorang pengembang? Bagaimana pertanyaan khusus HTML5 berhubungan dengan pustaka mandiri? Dan untuk apa nilainya, WebSockets BUKAN Socket.io. Socket.io adalah library yang bisa MENGGUNAKAN WebSockets, tapi saya ngelantur. Ini juga pertanyaan yang lebih spesifik yang berkaitan dengan perpustakaan tentang pengiriman data hanya ke klien tertentu, bukan tentang teknologi itu sendiri.
Levi Roberts
@ bugwheels94 Tidak juga, posting ini dari tahun 2011 dan karena nodejs memiliki banyak perubahan berdasarkan kode. posting ini jelas merupakan pertanyaan / jawaban yang valid untuk masalah ini.
Nizar B.

Jawaban:

102

Ketika seorang pengguna terhubung, itu harus mengirim pesan ke server dengan nama pengguna yang harus unik, seperti email.

Sepasang nama pengguna dan soket harus disimpan dalam objek seperti ini:

var users = {
    '[email protected]': [socket object],
    '[email protected]': [socket object],
    '[email protected]': [socket object]
}

Di klien, keluarkan objek ke server dengan data berikut:

{
    to:[the other receiver's username as a string],
    from:[the person who sent the message as string],
    message:[the message to be sent as string]
}

Di server, dengarkan pesan. Saat pesan diterima, kirimkan data ke penerima.

users[data.to].emit('receivedMessage', data)

Pada klien, dengarkan emit dari server yang disebut 'acceptMessage', dan dengan membaca data Anda dapat menangani siapa asalnya dan pesan yang dikirim.

Adam
sumber
27
Jika Anda menggunakan solusi ini maka Anda harus memahami: 1. Ketika pengguna memutuskan koneksi Anda harus membersihkan objek 'pengguna' 2. Itu tidak mendukung koneksi kedua - misalnya dari browser lain. Jadi jika pengguna terhubung dari browser lain - koneksi lama akan diganti.
Vladimir Kurijov
1
bagaimana Anda menyimpan objek soket di datastore? Saya berasumsi ini tidak berfungsi jika Anda memiliki lebih dari satu proses node.
chovy
@chovy Anda harus menggunakan redis. Periksa github.com/LearnBoost/Socket.IO/wiki/Configuring-Socket.IO
Vladimir Kurijov
11
Saya menyarankan untuk tidak menggunakan solusi ini. Saya akhirnya membuang banyak waktu untuk mencoba mengatasi keterbatasan pendekatan ini. Lihat solusi @ az7ar dan penjelasan ini mengapa lebih baik .
Daniel Que
@Daniel +1. Jauh lebih baik untuk menggunakan fungsionalitas asli. Terima kasih!
Aaron Lelevier
278

Anda dapat menggunakan ruang socket.io. Dari sisi klien, keluarkan acara ("gabung" dalam hal ini, bisa apa saja) dengan pengenal unik apa pun (email, id).

Sisi klien:

var socket = io.connect('http://localhost');
socket.emit('join', {email: user1@example.com});

Sekarang, dari sisi server gunakan informasi itu untuk membuat ruang unik bagi pengguna tersebut

Sisi server:

var io = require('socket.io').listen(80);

io.sockets.on('connection', function (socket) {
  socket.on('join', function (data) {
    socket.join(data.email); // We are using room of socket io
  });
});

Jadi, sekarang setiap pengguna telah bergabung dengan ruang yang dinamai menurut email pengguna. Jadi, jika Anda ingin mengirim pesan kepada pengguna tertentu, Anda hanya perlu melakukannya

Sisi server:

io.sockets.in('[email protected]').emit('new_msg', {msg: 'hello'});

Hal terakhir yang harus dilakukan di sisi klien adalah mendengarkan peristiwa "new_msg".

Sisi klien:

socket.on("new_msg", function(data) {
    alert(data.msg);
}

Saya harap Anda mengerti.

az7ar
sumber
3
tolong ubah baris ini io.socket.in ('[email protected] '). emit (' new_msg ', {msg:' hello '}); seperti ini io.sockets.in ('[email protected] '). emit (' new_msg ', {msg:' hello '});
silvesterprabu
43
Jawaban ini jauh lebih baik daripada jawaban yang diterima saat ini. Inilah alasannya: 1) Anda tidak perlu mengelola dan membersihkan rangkaian klien global. 2) Ini berfungsi bahkan jika pengguna memiliki banyak tab yang terbuka di halaman yang sama. 3) Dapat dengan mudah diperpanjang untuk bekerja dengan cluster node (banyak proses) dengan socket.io-redis.
Daniel Que
2
bagaimana Anda membuat {email: [email protected]}berbeda untuk semua koneksi Bukankah semua klien yang pergi ke aplikasi memiliki pengguna [email protected]bagaimana saya membuatnya menjadi pengguna [email protected]untuk klien kedua yang terhubung sehingga saya bisa memiliki ruangan yang berbeda. maaf jika ini pertanyaan yang mengganggu.
jack blank
2
menyukai solusinya, tetapi saya yakin keamanan terganggu di sini. Bagaimana jika saya mengubah email di skrip di sisi klien. Sekarang saya juga bisa membaca pesan pribadi lainnya. Apa yang kamu katakan?
Gopinath Shiva
3
tidak harus email Saya sebutkan pengenal unik apa pun
az7ar
32

PASTI: Sederhananya,

Inilah yang Anda butuhkan:

io.to(socket.id).emit("event", data);

setiap kali pengguna bergabung ke server, detail soket akan dibuat termasuk ID. Ini adalah ID yang sangat membantu untuk mengirim pesan ke orang-orang tertentu.

pertama kita perlu menyimpan semua socket.ids dalam array,

var people={};

people[name] =  socket.id;

di sini nama adalah nama penerima. Contoh:

people["ccccc"]=2387423cjhgfwerwer23;

Jadi, sekarang kita bisa mendapatkan socket.id itu dengan nama penerima setiap kali kita mengirim pesan:

untuk ini kita perlu mengetahui nama penerima. Anda perlu mengirimkan nama penerima ke server.

hal terakhir adalah:

 socket.on('chat message', function(data){
io.to(people[data.receiver]).emit('chat message', data.msg);
});

Semoga ini bekerja dengan baik untuk Anda.

Semoga berhasil!!

Trojan
sumber
Bisakah Anda membuat kode sisi klien dan sisi server.? Saya baru dalam pemrograman scoket. [email protected]
Harish Mahajan
@HARISH, lihat tautan di bawah ini, jelaskan apa yang sebenarnya terjadi dari sisi klien..saya harap ini membantu Anda lebih .. socket.io/get-started/chat
Trojan
2
Tetapi bagaimana jika pengguna mengobrol dengan 2 orang lainnya pada saat yang bersamaan. Akankah pesan dari kedua pengguna masuk di kedua jendela?
Sharan Mohandas
Jika ada lebih dari dua pengguna, itu tidak akan berfungsi dengan baik
Mohhamad Hasham
setiap kali pengguna menghubungkan perubahan id soket sehingga jika pengguna membuka aplikasi Anda di banyak tab, itu akan mendapat respons ke salah satu yang telah Anda simpan dan kirim ke koneksi soket lain
Vikas Kandari
8

Anda dapat merujuk ke ruang socket.io . Ketika Anda jabat tangan soket - Anda dapat bergabung dengannya ke ruang bernama, misalnya "pengguna. # {Userid}".

Setelah itu, Anda dapat mengirim pesan pribadi ke klien mana pun dengan nama yang sesuai, misalnya:

io.sockets.in ('user.125'). emit ('new_message', {text: "Hello world"})

Dalam operasi di atas kami mengirim "pesan_baru" ke pengguna "125".

Terima kasih.

Vladimir Kurijov
sumber
Hai sobat, terima kasih atas jawaban pertama Anda, saya akan mencobanya dan memberi tahu Anda tentang itu, karena saya tidak ingin membangun obrolan tetapi utusan pribadi seperti yang dapat Anda gunakan di jaringan Facebook.
Nizar B.
Adakah yang bisa membantu saya dengan masalah ini, saya benar-benar buntu, saya ingin menambahkan nama pengguna yang ditautkan ke soket saya dan mengizinkan aplikasi saya mengirim pesan ke pengguna tertentu, tidak ada ruang obrolan, ini adalah Facebook seperti messenger. Terima kasih jika Anda tahu!
Nizar B.
Pertama-tama, Anda harus memahami bahwa nama pengguna ini harus unik untuk semua pengguna. Dan yang kedua - apakah Anda tidak lupa untuk berlangganan pesan yang dipancarkan di sisi klien?
Vladimir Kurijov
Masalah dengan ini adalah Anda kehilangan kemampuan untuk menggunakan panggilan balik, karena panggilan tidak diizinkan dalam siaran, yang sebenarnya Anda lakukan di sini, siaran ke kamar pribadinya.
bluehallu
@VladimirKurijov, Tuan Katcha tidak ingin menggunakan Kamar dan saya setuju itu bukan solusi untuk masalahnya.
miksiii
4

Dalam proyek perusahaan kami, kami menggunakan pendekatan "kamar" dan namanya adalah kombinasi dari ID pengguna dari semua pengguna dalam percakapan sebagai pengenal unik (implementasi kami lebih seperti facebook messenger), contoh:

| id | nama | 1 | Scott | 2 | Susan

Nama "kamar" akan menjadi "1-2" (id dipesan Asc.) dan pada putuskan soket.io secara otomatis membersihkan kamar

dengan cara ini Anda mengirim pesan hanya ke ruangan itu dan hanya ke pengguna online (terhubung) (lebih sedikit paket yang dikirim ke seluruh server).

Rami
sumber
1

Biarkan saya membuatnya lebih sederhana dengan ruang socket.io. meminta server dengan pengenal unik untuk bergabung dengan server. di sini kami menggunakan email sebagai pengenal unik.

Klien Socket.io

socket.on('connect', function () {
  socket.emit('join', {email: user@example.com});
});

Saat pengguna bergabung dengan server, buat ruang untuk pengguna tersebut

Server Socket.io

io.on('connection', function (socket) {
   socket.on('join', function (data) {    
    socket.join(data.email);
  });
});

Sekarang kita siap bergabung. biarkan memancarkan sesuatu dari serverto , sehingga pengguna dapat mendengarkan.

Server Socket.io

io.to('[email protected]').emit('message', {msg: 'hello world.'});

Mari selesaikan topik dengan mendengarkan messageacara dari sisi klien

socket.on("message", function(data) {
  alert(data.msg);
});

Referensi dari ruang Socket.io

Lalit Mohan
sumber