socket.io를 사용하여 특정 클라이언트에 메시지를 보내는 방법


96

나는 socket.io + node.js로 시작하고, 로컬로 메시지를 보내고 socket.broadcast.emit()기능 을 브로드 캐스트하는 방법을 알고 있습니다 .-연결된 모든 클라이언트가 동일한 메시지를받습니다.

이제 특정 클라이언트에게 개인 메시지를 보내는 방법을 알고 싶습니다. 즉, 두 사람 (Client-To-Client 스트림) 간의 개인 채팅을위한 소켓 하나를 의미합니다. 감사.


죄송합니다 psiphi75 그러나이 링크는 내 답변에 응답하지 않으며 중복 질문이 아닙니다.
Nizar B. 2013-07-05

1
@ psiphi75, 그것은 방법을 중복 없습니다
softvar

1
@psiphi 같은 사람을 참을 수 없습니다. 당신은 개발자입니까? HTML5 관련 질문은 독립형 라이브러리와 어떤 관련이 있습니까? 그리고 그것이 가치있는 것에 대해 WebSocket은 Socket.io가 아닙니다. Socket.io는 WebSockets를 사용할 수있는 라이브러리이지만 나는 우회합니다. 이것은 또한 기술 자체가 아닌 특정 클라이언트에게만 데이터를 보내는 것에 관한 라이브러리와 관련된보다 구체적인 질문입니다.
Levi Roberts


@ bugwheels94 실제로이 게시물은 2011 년의 게시물이며 nodejs는 코드 측면에서 많은 변경 사항을 가졌습니다. 이 게시물은 확실히이 문제에 대한 유효한 질문 / 답변입니다.
Nizar B.

답변:


102

사용자가 연결되면 이메일과 같이 고유해야하는 사용자 이름으로 서버에 메시지를 보내야합니다.

사용자 이름과 소켓 쌍은 다음과 같은 객체에 저장되어야합니다.

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

클라이언트에서 다음 데이터를 사용하여 서버에 개체를 내 보냅니다.

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

서버에서 메시지를 수신합니다. 메시지가 수신되면 데이터를 수신자에게 내 보냅니다.

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

클라이언트에서 'receivedMessage'라는 서버의 방출을 수신하고 데이터를 읽음으로써 누가 보낸 사람과 보낸 메시지를 처리 ​​할 수 ​​있습니다.


27
이 솔루션을 사용하는 경우 다음을 이해해야합니다. 1. 사용자가 연결을 끊으면 '사용자'개체를 정리해야합니다. 2. 두 번째 연결을 지원하지 않습니다 (예 : 다른 브라우저에서). 따라서 사용자가 다른 브라우저에서 연결하면 이전 연결이 무시됩니다.
블라디미르 Kurijov

1
소켓 객체를 데이터 저장소에 어떻게 저장합니까? 두 개 이상의 노드 프로세스가 있으면 이것이 작동하지 않는다고 가정합니다.
chovy

@chovy 당신은 redis를 사용해야합니다. 이 확인 github.com/LearnBoost/Socket.IO/wiki/Configuring-Socket.IO
블라디미르 Kurijov

11
이 솔루션을 사용하지 않는 것이 좋습니다. 이 접근 방식의 한계를 극복하기 위해 많은 시간을 낭비했습니다. @ az7ar의 솔루션더 나은 이유는설명을 참조하십시오 .
Daniel Que

@DanielQue +1. 기본 기능을 사용하는 것이 훨씬 좋습니다. 감사!
Aaron Lelevier 2015

277

socket.io 방을 사용할 수 있습니다. 클라이언트 측에서 고유 식별자 (이메일, ID)를 사용하여 이벤트 (이 경우 "조인"은 무엇이든 가능)를 내 보냅니다.

고객 입장에서:

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

이제 서버 측에서 해당 정보를 사용하여 해당 사용자를위한 고유 한 공간을 만듭니다.

서버 측:

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

이제 모든 사용자가 사용자의 이메일 이름을 딴 방에 참여했습니다. 따라서 특정 사용자에게 메시지를 보내려면

서버 측:

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

클라이언트 측에서 마지막으로 할 일은 "new_msg"이벤트를 수신하는 것입니다.

고객 입장에서:

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

나는 당신이 아이디어를 얻길 바랍니다.


3
이 줄을 변경하십시오. io.socket.in ('user1@example.com '). emit ('new_msg ', {msg :'hello '}); 다음과 같이 io.sockets.in ('user1@example.com '). emit ('new_msg ', {msg :'hello '});
silvesterprabu 2014

42
이 답변은 현재 허용되는 답변보다 훨씬 낫습니다. 그 이유는 다음과 같습니다. 1) 글로벌 클라이언트 배열을 관리하고 정리할 필요가 없습니다. 2) 사용자가 같은 페이지에 여러 개의 탭이 열려 있어도 작동합니다. 3) .NET을 사용하여 노드 클러스터 (다중 프로세스)와 함께 작업하도록 쉽게 확장 할 수 있습니다 socket.io-redis.
Daniel Que

2
{email: user1@example.com}모든 연결에 대해 어떻게 다르게 만들 수 있습니까? 앱으로 이동하는 모든 클라이언트가 사용자를 갖지 user1@example.com않을 것입니다. 어떻게 user2@example.com연결하는 두 번째 클라이언트에 대해 사용자 를 만들어 다른 방을 가질 수 있습니까? 성가신 질문이라면 죄송합니다.
잭 블랭크

2
솔루션이 마음에 들었지만 여기서 보안이 손상되었다고 생각합니다. 클라이언트 측 스크립트에서 이메일을 변경하면 어떻게됩니까? 이제 다른 비공개 메시지도 읽을 수 있습니다. 당신이 무슨 말을하는거야?
피나 시바

3
내가 어떤 고유 한 식별자를 언급 이메일 될 필요가 없습니다
az7ar

32

확실히 : 간단히 말해서

이것이 필요한 것입니다.

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

사용자가 서버에 가입 할 때마다 ID를 포함한 소켓 세부 정보가 생성됩니다. 이것은 특정 사람들에게 메시지를 보내는 데 정말 도움이되는 ID입니다.

먼저 모든 socket.id를 배열에 저장해야합니다.

var people={};

people[name] =  socket.id;

여기 이름은 수신자 이름입니다. 예:

people["ccccc"]=2387423cjhgfwerwer23;

이제 메시지를 보낼 때마다 수신자 이름과 함께 socket.id를 얻을 수 있습니다.

이를 위해 수신자 이름을 알아야합니다. 수신자 이름을 서버로 내 보내야합니다.

마지막으로 :

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

이것이 당신을 위해 잘 작동하기를 바랍니다.

행운을 빕니다!!


클라이언트 측 및 서버 측 코드를 만들 수 있습니까? 나는 scoket 프로그래밍이 처음입니다. hmahajan.dmi@gmail.com
Harish 마하 잔

@HARISH은 아래 링크를 참조 정말이 더 도움이 클라이언트 side..i 희망 ..에서 일어나고 대해 설명 socket.io/get-started/chat
트로이 목마

2
그러나 사용자가 동시에 다른 2 명과 채팅을하고 있다면 어떨까요? 두 사용자의 메시지가 두 창에 모두 표시되지 않습니까?
Sharan Mohandas

사용자가 세 명 이상이면 제대로 작동하지 않습니다
Mohhamad Hasham

사용자가 소켓 ID 변경 사항을 연결할 때마다 사용자가 여러 탭에서 앱을 열 경우 저장하고 다른 소켓 연결로 보낸 하나에 대한 응답을 받게됩니다
Vikas Kandari

8

socket.io 방을 참조 할 수 있습니다 . 소켓을 핸드 셰이 킹하면 "user. # {userid}"와 같이 이름이 지정된 방에 그를 연결할 수 있습니다.

그런 다음 편리한 이름으로 모든 클라이언트에게 비공개 메시지를 보낼 수 있습니다. 예를 들면 다음과 같습니다.

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

위의 작업에서 사용자 "125"에게 "new_message"를 보냅니다.

감사.


안녕 친구, 첫 번째 답변 주셔서 감사합니다. 저는 채팅을 만들고 싶지 않지만 Facebook 네트워크에서 사용할 수있는 개인 메신저를 만들고 싶지 않기 때문에 시도해보고 알려 드리겠습니다.
Nizar B.

누군가 가이 문제에 대해 나를 도울 수 있습니까? 정말 막혔습니다. 소켓에 연결된 사용자 이름을 추가하고 내 응용 프로그램이 채팅방이 아닌 특정 사용자에게 메시지를 보낼 수 있도록하고 싶습니다. 메신저와 같은 Facebook입니다. 알고 있으면 감사합니다!
Nizar B. 2013

처음에는이 사용자 이름이 모든 사용자에게 고유해야한다는 것을 이해해야합니다. 그리고 두 번째-클라이언트 측에서 보내는 메시지를 구독하는 것을 잊지 않았습니까?
Vladimir Kurijov

이것의 문제는 콜백을 사용할 수있는 능력을 잃어버린다는 것입니다. 그것은 방송에서 허용되지 않기 때문입니다. 이것이 당신이 실제로하는 일인 그의 개인 방으로의 방송입니다.
bluehallu

@VladimirKurijov, Mr Katcha는 Rooms를 사용하고 싶지 않으며 그의 문제에 대한 해결책이 아니라는 데 동의합니다.
miksiii

4

우리 회사의 프로젝트에서 우리는 "rooms"접근 방식을 사용하고 있으며 그 이름은 대화에있는 모든 사용자의 사용자 ID를 고유 식별자로 조합 한 것입니다 (우리의 구현은 페이스 북 메신저와 비슷합니다). 예 :

| id | 이름 | 1 | 스콧 | 2 | 수잔

"room"이름은 "1-2"(ID는 Asc로 정렬 됨)이며 연결이 끊기면 socket.io가 자동으로 방을 정리합니다.

이렇게하면 해당 룸에만 메시지를 보내고 온라인 (연결된) 사용자에게만 메시지를 보냅니다 (서버 전체에 패키지가 더 적게 전송 됨).


1

socket.io 방으로 더 간단하게 만들겠습니다. 서버에 가입하려면 고유 식별자가있는 서버를 요청합니다. 여기서는 이메일을 고유 식별자로 사용합니다.

클라이언트 Socket.io

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

사용자가 서버에 가입하면 해당 사용자를위한 방을 만듭니다.

서버 Socket.io

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

이제 우리는 모두 합류 할 준비가되었습니다. to사용자가들을 수 있도록 서버 룸 에서 무언가를 내보내 도록합니다.

서버 Socket.io

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

message클라이언트 측 에서 이벤트를 듣고 주제를 마무리하십시오.

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

Socket.io 방의 참조

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.