Cách gửi tin nhắn đến một khách hàng cụ thể bằng socket.io


95

Tôi đang bắt đầu với socket.io + node.js, tôi biết cách gửi tin nhắn cục bộ và socket.broadcast.emit()chức năng quảng bá : - tất cả các máy khách được kết nối đều nhận được cùng một thông báo.

Bây giờ, tôi muốn biết cách gửi tin nhắn riêng tư đến một khách hàng cụ thể, ý tôi là một ổ cắm cho cuộc trò chuyện riêng tư giữa 2 người (luồng Khách hàng - Khách hàng). Cảm ơn.


Xin lỗi psiphi75 nhưng liên kết này không trả lời câu trả lời của tôi, không phải là một câu hỏi trùng lặp.
Nizar B.

1
@ psiphi75, nó không có cách nào một bản sao
softvar

1
Không thể chịu được những người như @psiphi. Bạn thậm chí là một nhà phát triển? Một câu hỏi cụ thể về HTML5 liên quan như thế nào đến một thư viện độc lập? Và đối với những gì nó đáng giá, WebSockets KHÔNG phải là Socket.io. Socket.io là một thư viện có thể SỬ DỤNG WebSockets, nhưng tôi lạc đề. Đây cũng là một câu hỏi cụ thể hơn liên quan đến thư viện về việc chỉ gửi dữ liệu đến các khách hàng cụ thể, không phải về bản thân công nghệ.
Levi Roberts


@ bugwheels94 Không hẳn, bài đăng này là từ năm 2011 và vì nodejs đã có vô số thay đổi về mã. bài đăng này chắc chắn là một câu hỏi / câu trả lời hợp lệ cho vấn đề này.
Nizar B.

Câu trả lời:


101

Khi người dùng kết nối, nó sẽ gửi tin nhắn đến máy chủ với tên người dùng phải là duy nhất, như email.

Một cặp tên người dùng và ổ cắm sẽ được lưu trữ trong một đối tượng như sau:

var users = {
    'userA@example.com': [socket object],
    'userB@example.com': [socket object],
    'userC@example.com': [socket object]
}

Trên máy khách, phát một đối tượng tới máy chủ với dữ liệu sau:

{
    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]
}

Trên máy chủ, lắng nghe tin nhắn. Khi một tin nhắn được nhận, phát dữ liệu đến người nhận.

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

Trên máy khách, lắng nghe phát ra từ máy chủ được gọi là "ReceivedMessage" và bằng cách đọc dữ liệu, bạn có thể xử lý dữ liệu đó đến từ ai và tin nhắn đã được gửi.


26
Nếu bạn sử dụng giải pháp này thì bạn phải hiểu: 1. Khi người dùng ngắt kết nối, bạn phải dọn dẹp đối tượng 'người dùng' 2. Nó không hỗ trợ kết nối thứ hai - ví dụ từ trình duyệt khác. Vì vậy, nếu người dùng kết nối từ trình duyệt khác - kết nối cũ sẽ bị ghi đè.
Vladimir Kurijov

1
bạn sẽ lưu trữ đối tượng socket như thế nào trong kho dữ liệu? Tôi giả sử điều này không hoạt động nếu bạn có nhiều hơn một quy trình nút.
chovy

@chovy bạn phải sử dụng redis. Kiểm tra github.com/LearnBoost/Socket.IO/wiki/Configuring-Socket.IO
Vladimir Kurijov

11
Tôi đề nghị không sử dụng giải pháp này. Cuối cùng tôi đã lãng phí rất nhiều thời gian để cố gắng khắc phục những hạn chế của cách tiếp cận này. Xem giải pháp của @ az7argiải thích này để biết lý do tại sao nó tốt hơn .
Daniel Que

@DanielQue +1. Cách tốt hơn để sử dụng chức năng gốc. Cảm ơn!
Aaron Lelevier

273

Bạn có thể sử dụng phòng socket.io. Từ phía máy khách phát ra một sự kiện ("tham gia" trong trường hợp này, có thể là bất kỳ thứ gì) với bất kỳ số nhận dạng duy nhất nào (email, id).

Phía khách hàng:

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

Bây giờ, từ phía máy chủ, hãy sử dụng thông tin đó để tạo một phòng duy nhất cho người dùng đó

Phía máy chủ:

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

Vì vậy, bây giờ mỗi người dùng đã tham gia một phòng được đặt tên theo email của người dùng. Vì vậy, nếu bạn muốn gửi cho một người dùng cụ thể một tin nhắn, bạn chỉ cần

Phía máy chủ:

io.sockets.in('user1@example.com').emit('new_msg', {msg: 'hello'});

Điều cuối cùng cần làm ở phía máy khách là lắng nghe sự kiện "new_msg".

Phía khách hàng:

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

Tôi hy vọng bạn có được ý tưởng.


2
vui lòng thay đổi dòng này io.socket.in ('user1@example.com '). release (' new_msg ', {msg:' hello '}); như thế này io.sockets.in ('user1@example.com '). release (' new_msg ', {msg:' hello '});
silvesterprabu

42
Câu trả lời này là nhiều hơn câu trả lời chấp nhận hiện nay. Đây là lý do tại sao: 1) Bạn không phải quản lý và dọn dẹp mảng khách hàng toàn cầu. 2) Nó hoạt động ngay cả khi người dùng mở nhiều tab trên cùng một trang. 3) Nó có thể dễ dàng mở rộng để làm việc với một cụm nút (nhiều quy trình) với socket.io-redis.
Daniel Que

2
làm thế nào để bạn thực hiện {email: user1@example.com}khác nhau cho tất cả các kết nối wouldnt tất cả khách hàng rằng truy cập ứng dụng có sử dụng user1@example.comthế nào tôi sẽ làm cho nó sử dụng user2@example.comcho khách hàng thứ hai kết nối để tôi có thể có phòng khác nhau. xin lỗi nếu đây là một câu hỏi khó chịu.
jack trống

2
yêu thích giải pháp, nhưng tôi tin rằng an ninh đã bị xâm phạm ở đây. Điều gì sẽ xảy ra nếu tôi thay đổi email trong tập lệnh ở phía máy khách. Bây giờ tôi cũng có thể đọc các tin nhắn riêng tư khác. Bạn đang nói gì vậy
Gopinath Shiva

3
nó không phải là email tôi đã đề cập bất kỳ định danh duy nhất
az7ar

32

CHẮC CHẮN: Đơn giản,

Đây là những gì bạn cần :

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

bất cứ khi nào người dùng tham gia vào máy chủ, chi tiết ổ cắm sẽ được tạo bao gồm cả ID. Đây là ID thực sự giúp gửi một thông điệp đến những người cụ thể.

đầu tiên chúng ta cần lưu trữ tất cả các socket.ids trong mảng,

var people={};

people[name] =  socket.id;

ở đây tên là tên người nhận. Thí dụ:

people["ccccc"]=2387423cjhgfwerwer23;

Vì vậy, bây giờ chúng ta có thể lấy socket.id đó với tên người nhận bất cứ khi nào chúng ta gửi tin nhắn:

vì điều này, chúng ta cần biết tên người nhận. Bạn cần phát ra tên người nhận cho máy chủ.

điều cuối cùng là:

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

Hy vọng điều này làm việc tốt cho bạn.

Chúc may mắn!!


Bạn có thể tạo mã phía máy khách và mã phía máy chủ.? Tôi là người mới trong lập trình scoket. hmahajan.dmi@gmail.com
Harish Mahajan

@HARISH, tham khảo bên dưới liên kết, giải thích những gì thực sự xảy ra từ khách hàng side..i hy vọng điều này giúp bạn biết thêm .. socket.io/get-started/chat
Trojan

2
Nhưng điều gì sẽ xảy ra nếu người dùng đang trò chuyện với 2 người khác cùng lúc. Sẽ không có thông báo từ cả hai người dùng trong cả hai cửa sổ?
Sharan Mohandas

Nếu có nhiều hơn hai người dùng, nó sẽ không hoạt động đúng
Mohhamad Hasham

mỗi khi người dùng kết nối id socket thay đổi, vì vậy trong trường hợp người dùng mở ứng dụng của bạn trong nhiều tab, nó sẽ nhận được phản hồi cho một tab mà bạn đã lưu trữ và gửi đến các kết nối socket khác
Vikas Kandari

8

Bạn có thể tham khảo các phòng socket.io . Khi bạn bắt tay socket - bạn có thể cùng anh ấy đến phòng đã đặt tên, chẳng hạn như "user. # {Userid}".

Sau đó, bạn có thể gửi tin nhắn riêng cho bất kỳ khách hàng nào bằng tên thuận tiện, ví dụ:

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

Trong thao tác trên, chúng tôi gửi "new_message" tới người dùng "125".

cảm ơn.


Xin chào người bạn đời, cảm ơn câu trả lời đầu tiên của bạn, tôi sẽ thử nó và cho bạn biết về điều đó, bởi vì tôi không muốn xây dựng một cuộc trò chuyện mà là một trình nhắn tin riêng tư như bạn có thể sử dụng trên mạng Facebook.
Nizar B.

Ai đó có thể giúp tôi vấn đề này không, tôi thực sự bị mắc kẹt, tôi muốn thêm tên người dùng được liên kết với ổ cắm của mình và cho phép ứng dụng của tôi gửi tin nhắn đến một người dùng cụ thể, không có phòng trò chuyện, đó là một Facebook giống như Messenger. Cảm ơn nếu bạn biết!
Nizar B.

Lúc đầu, bạn phải hiểu rằng tên người dùng này phải là duy nhất trên tất cả người dùng. Và điều thứ hai - bạn đã quên đăng ký nhận tin nhắn đã phát ở phía máy khách chưa?
Vladimir Kurijov

Vấn đề với điều này là bạn mất khả năng sử dụng các cuộc gọi lại, vì chúng không được phép trong các chương trình phát sóng, đó là những gì bạn thực sự đang làm ở đây, một chương trình phát sóng đến phòng riêng của anh ấy.
bluehallu

@VladimirKurijov, Ông Katcha không muốn sử dụng Phòng và tôi đồng ý rằng đó không phải là giải pháp cho vấn đề của ông ấy.
miksiii 16/02/15

4

Trong một dự án của công ty chúng tôi, chúng tôi đang sử dụng phương pháp tiếp cận "phòng" và tên của nó là sự kết hợp của id người dùng của tất cả người dùng trong một cuộc trò chuyện như một số nhận dạng duy nhất (cách triển khai của chúng tôi giống như facebook messenger), ví dụ:

| id | tên | 1 | Scott | 2 | Susan

tên "phòng" sẽ là "1-2" (id được sắp xếp theo thứ tự Asc.) và khi ngắt kết nối socket.io sẽ tự động dọn dẹp phòng

theo cách này, bạn chỉ gửi tin nhắn đến phòng đó và chỉ cho người dùng trực tuyến (được kết nối) (ít gói được gửi qua máy chủ).


1

Hãy để tôi làm cho nó đơn giản hơn với các phòng socket.io. yêu cầu máy chủ có số nhận dạng duy nhất tham gia máy chủ. ở đây chúng tôi đang sử dụng email làm mã định danh duy nhất.

Khách hàng Socket.io

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

Khi người dùng tham gia một máy chủ, hãy tạo một phòng cho người dùng đó

Máy chủ Socket.io

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

Bây giờ chúng ta đã sẵn sàng với việc tham gia. để phát ra thứ gì đó từ tophòng máy chủ để người dùng có thể nghe.

Máy chủ Socket.io

io.to('user@example.com').emit('message', {msg: 'hello world.'});

Hãy kết thúc chủ đề với việc lắng nghe messagesự kiện từ phía khách hàng

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

Tham khảo từ phòng Socket.io

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.