115

我从 socket.io + node.js 开始,我知道如何在本地发送消息并广播socket.broadcast.emit()功能:- 所有连接的客户端都收到相同的消息。

现在,我想知道如何向特定客户端发送私人消息,我的意思是两个人之间私人聊天的一个套接字(客户端到客户端流)。谢谢。

4

7 回答 7

312

您可以使用 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);
}

我希望你能明白。

于 2013-07-08T20:07:43.203 回答
109

When a user connects, it should send a message to the server with a username which has to be unique, like an email.

A pair of username and socket should be stored in an object like this:

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

On the client, emit an object to the server with the following data:

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

On the server, listen for messages. When a message is received, emit the data to the receiver.

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

On the client, listen for emits from the server called 'receivedMessage', and by reading the data you can handle who it came from and the message that was sent.

于 2013-07-08T10:01:26.183 回答
42

肯定: 简单地说,

这就是你需要的:

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

每当用户加入服务器时,都会生成套接字详细信息,包括 ID。这是真正有助于向特定人发送消息的 ID。

首先我们需要将所有socket.ids存储在数组中,

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

希望这对你有用。

祝你好运!!

于 2016-10-20T13:48:44.863 回答
12

你可以参考 socket.io rooms。当您握手套接字时 - 您可以将他加入命名房间,例如“user.#{userid}”。

之后,您可以通过方便的名称向任何客户端发送私人消息,例如:

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

在上述操作中,我们将“new_message”发送给用户“125”。

谢谢。

于 2013-07-05T14:18:40.910 回答
6

正如az7ar的回答说得很好,但让我用 socket.io 房间让它变得更简单。请求具有唯一标识符的服务器加入服务器。在这里,我们使用电子邮件作为唯一标识符。

客户端套接字.io

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

当用户加入服务器时,为该用户创建一个房间

服务器套接字.io

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

现在我们都准备好加入了。让从服务器to机房发出一些东西,以便用户可以收听。

服务器套接字.io

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

message让我们通过向客户端监听事件来完成主题

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

来自 Socket.io 房间的参考

于 2019-03-20T11:47:39.880 回答
6

In a project of our company we are using "rooms" approach and it's name is a combination of user ids of all users in a conversation as a unique identifier (our implementation is more like facebook messenger), example:

|id | name |1 | Scott |2 | Susan

"room" name will be "1-2" (ids are ordered Asc.) and on disconnect socket.io automatically cleans up the room

this way you send messages just to that room and only to online (connected) users (less packages sent throughout the server).

于 2016-07-20T19:22:04.190 回答
1

这是 Android Client + Socket IO Server 的完整解决方案(代码很多但有效)。当涉及到套接字 io 时,似乎缺乏对 Android 和 IOS 的支持,这是一种悲剧。

基本上通过加入来自mysql或mongo的用户唯一ID然后对其进行排序来创建房间名称(在Android客户端完成并发送到服务器)。 所以每对都有一个独特但共同的房间名称。然后就在那个房间里聊天。

快速参考如何在 Android 中创建房间

 // Build The Chat Room
        if (Integer.parseInt(mySqlUserId) < Integer.parseInt(toMySqlUserId)) {
            room = "ic" + mySqlUserId + toMySqlUserId;
        } else {
            room = "ic" + toMySqlUserId + mySqlUserId;
        }

完整作品

包Json

"dependencies": {
    "express": "^4.17.1",
    "socket.io": "^2.3.0"
  },
  "devDependencies": {
    "nodemon": "^2.0.6"
  }

套接字 IO 服务器

app = require('express')()
http = require('http').createServer(app)
io = require('socket.io')(http)

app.get('/', (req, res) => {

    res.send('Chat server is running on port 5000')
})

io.on('connection', (socket) => {

    // console.log('one user connected ' + socket.id);

    // Join Chat Room
    socket.on('join', function(data) {

        console.log('======Joined Room========== ');
        console.log(data);

        // Json Parse String To Access Child Elements
        var messageJson = JSON.parse(data);
        const room = messageJson.room;
        console.log(room);

        socket.join(room);

    });

    // On Receiving Individual Chat Message (ic_message)
    socket.on('ic_message', function(data) {
        console.log('======IC Message========== ');
        console.log(data);

        // Json Parse String To Access Child Elements
        var messageJson = JSON.parse(data);
        const room = messageJson.room;
        const message = messageJson.message;

        console.log(room);
        console.log(message);

        // Sending to all clients in room except sender
        socket.broadcast.to(room).emit('new_msg', {
            msg: message
        });

    });

    socket.on('disconnect', function() {
        console.log('one user disconnected ' + socket.id);
    });

});

http.listen(5000, () => {

    console.log('Node app is running on port 5000')
})

Android Socket IO 类

public class SocketIOClient {

    public Socket mSocket;

    {
        try {
            mSocket = IO.socket("http://192.168.1.5:5000");
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
    }

    public Socket getSocket() {
        return mSocket;
    }
}

安卓活动

public class IndividualChatSocketIOActivity extends AppCompatActivity {

    // Activity Number For Bottom Navigation Menu
    private final Context mContext = IndividualChatSocketIOActivity.this;

    // Strings
    private String mySqlUserId;
    private String toMySqlUserId;

    // Widgets
    private EditText etTextMessage;
    private ImageView ivSendMessage;

    // Socket IO
    SocketIOClient socketIOClient = new SocketIOClient();
    private String room;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_chat);

        // Widgets
        etTextMessage = findViewById(R.id.a_chat_et_text_message);
        ivSendMessage = findViewById(R.id.a_chat_iv_send_message);

        // Get The MySql UserId from Shared Preference
        mySqlUserId = StartupMethods.getFromSharedPreferences("shared",
                                                              "id",
                                                              mContext);

        // Variables From Individual List Adapter
        Intent intent = getIntent();

        if (intent.hasExtra("to_id")) {

            toMySqlUserId = Objects.requireNonNull(Objects.requireNonNull(getIntent().getExtras())
                                                          .get("to_id"))
                                   .toString();
        }

        // Build The Chat Room
        if (Integer.parseInt(mySqlUserId) < Integer.parseInt(toMySqlUserId)) {
            room = "ic" + mySqlUserId + toMySqlUserId;
        } else {
            room = "ic" + toMySqlUserId + mySqlUserId;
        }

        connectToSocketIO();

        joinChat();

        leaveChat();

        getChatMessages();

        sendChatMessages();

    }

    @Override
    protected void onPause() {
        super.onPause();

    }

    private void connectToSocketIO() {

        socketIOClient.mSocket = socketIOClient.getSocket();
        socketIOClient.mSocket.on(Socket.EVENT_CONNECT_ERROR,
                                  onConnectError);
        socketIOClient.mSocket.on(Socket.EVENT_CONNECT_TIMEOUT,
                                  onConnectError);
        socketIOClient.mSocket.on(Socket.EVENT_CONNECT,
                                  onConnect);
        socketIOClient.mSocket.on(Socket.EVENT_DISCONNECT,
                                  onDisconnect);
        socketIOClient.mSocket.connect();
    }

    private void joinChat() {

        // Prepare To Send Data Through WebSockets
        JSONObject jsonObject = new JSONObject();

        // Header Fields
        try {

            jsonObject.put("room",
                           room);

            socketIOClient.mSocket.emit("join",
                                        String.valueOf(jsonObject));

        } catch (JSONException e) {
            e.printStackTrace();
        }

    }

    private void leaveChat() {
    }

    private void getChatMessages() {

        socketIOClient.mSocket.on("new_msg",
                                  new Emitter.Listener() {
                                      @Override
                                      public void call(Object... args) {
                                          try {
                                              JSONObject messageJson = new JSONObject(args[0].toString());
                                              String message = String.valueOf(messageJson);

                                              runOnUiThread(new Runnable() {
                                                  @Override
                                                  public void run() {
                                                      Toast.makeText(IndividualChatSocketIOActivity.this,
                                                                     message,
                                                                     Toast.LENGTH_SHORT)
                                                           .show();
                                                  }
                                              });
                                          } catch (JSONException e) {
                                              e.printStackTrace();
                                          }
                                      }
                                  });
    }

    private void sendChatMessages() {

        ivSendMessage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                String message = etTextMessage.getText()
                                              .toString()
                                              .trim();

                // Prepare To Send Data Thru WebSockets
                JSONObject jsonObject = new JSONObject();

                // Header Fields
                try {
                    jsonObject.put("room",
                                   room);

                    jsonObject.put("message",
                                   message);

                    socketIOClient.mSocket.emit("ic_message",
                                                String.valueOf(jsonObject));

                } catch (JSONException e) {
                    e.printStackTrace();
                }

            }
        });
    }

    public Emitter.Listener onConnect = new Emitter.Listener() {
        @Override
        public void call(Object... args) {

            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(IndividualChatSocketIOActivity.this,
                                   "Connected To Socket Server",
                                   Toast.LENGTH_SHORT)
                         .show();

                }
            });

            Log.d("TAG",
                  "Socket Connected!");
        }
    };

    private Emitter.Listener onConnectError = new Emitter.Listener() {
        @Override
        public void call(Object... args) {

            runOnUiThread(new Runnable() {
                @Override
                public void run() {

                }
            });
        }
    };
    private Emitter.Listener onDisconnect = new Emitter.Listener() {
        @Override
        public void call(Object... args) {

            runOnUiThread(new Runnable() {
                @Override
                public void run() {

                }
            });
        }
    };

}

安卓摇篮

// SocketIO
implementation ('io.socket:socket.io-client:1.0.0') {
    // excluding org.json which is provided by Android
    exclude group: 'org.json', module: 'json'
}
于 2021-01-19T08:35:24.513 回答