繁体   English   中英

如何使用 socket.io 向特定客户端发送消息

[英]How to send a message to a particular client with socket.io

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

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

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

我希望你能明白。

当用户连接时,它应该使用必须唯一的用户名向服务器发送消息,例如电子邮件。

一对用户名和套接字应该存储在这样的对象中:

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”的服务器发出的消息,通过读取数据,您可以处理它来自谁以及发送的消息。

当然:简单地说,

这是你需要的:

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

希望这对你有用。

祝你好运!!

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

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

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

在上面的操作中,我们向用户“125”发送“new_message”。

谢谢。

在我们公司的一个项目中,我们使用“房间”方法,它的名称是对话中所有用户的用户 ID 的组合作为唯一标识符(我们的实现更像是 Facebook 信使),例如:

|身份证 | 姓名 |1 | 斯科特 |2 | 苏珊

“房间”名称将是“1-2”(ID 以升序排列)并且在断开连接时 socket.io 会自动清理房间

通过这种方式,您只向那个房间发送消息,并且只向在线(连接)用户发送消息(整个服务器发送的包较少)。

正如az7ar 的回答说得很漂亮,但让我用 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 房间的参考

这是 Android Client + Socket IO Server 的完整解决方案(大量代码但有效)。 当谈到 socket 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'
}

我没有制作房间(因为您只想将消息发送给 1 个人) ,而是制作了一个内存数组:

clientSessions: Map<string, UserIdentifier> = new Map()

我这样做是为了我的用例,我想根据我设置的标识符获取我想要的套接字 ID。 map 中的键是我设置的标识符,值包括连接的那个套接字的 ID。 请参阅下面的服务器端代码。

客户端:

const socket = io('http://localhost:3200', {query: {randomKeyID: '123'}});

服务器端:

  handleDisconnect(client: Socket) {
    const query = client.handshake.query;
    const randomKeyID = <string> query.randomKeyID
    this.clientSessions.delete(randomKeyID);
    console.log(`Client disconnected: ${client.id}`);
  }

  handleConnection(client: Socket, ...args: any[]) {
    const query = client.handshake.query;
    const user: UserIdentifier = {
      id: client.id,
      randomKeyID: <string> query.randomKeyID
    }
    this.clientSessions.set(user.randomKeyID, user);
    console.log(`Client connected: ${client.id}`);
  }

在服务器端也添加了这个,以便轻松访问 websocket (服务器类型来自 socket.io)

  @WebSocketServer()
  server: Server;

所以,如果我想发送给特定的客户,我可以:

const { randomKeyID } = this.clientSessions.get(something);
this.server.to(randomKeyID).emit('clientListener', 'Hello');

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM