Sending message to a specific connected users using webSocket?
For people using ws
version 3 or above. If you want to use the answer provided by @ma11hew28, simply change this block as following.
webSocketServer.on('connection', function (webSocket) {
var userID = parseInt(webSocket.upgradeReq.url.substr(1), 10)
webSocketServer.on('connection', function (webSocket, req) {
var userID = parseInt(req.url.substr(1), 10)
ws
package has moved upgradeReq
to request object and you can check the following link for further detail.
Reference: https://github.com/websockets/ws/issues/1114
This is not only the right way to go, but the only way. Basically each connection needs a unique ID. Otherwise you won't be able to identify them, it's as simple as that.
Now how you will represent it it's a different thing. Making an object with id
and connection
properties is a good way to do that ( I would definitely go for it ). You could also attach the id
directly to connection object.
Also remember that if you want communication between users, then you have to send target user's ID as well, i.e. when user A wants to send a message to user B, then obviously A has to know the ID of B.
Here's a simple chat server private/direct messaging.
package.json
{
"name": "chat-server",
"version": "0.0.1",
"description": "WebSocket chat server",
"dependencies": {
"ws": "0.4.x"
}
}
server.js
var webSocketServer = new (require('ws')).Server({port: (process.env.PORT || 5000)}),
webSockets = {} // userID: webSocket
// CONNECT /:userID
// wscat -c ws://localhost:5000/1
webSocketServer.on('connection', function (webSocket) {
var userID = parseInt(webSocket.upgradeReq.url.substr(1), 10)
webSockets[userID] = webSocket
console.log('connected: ' + userID + ' in ' + Object.getOwnPropertyNames(webSockets))
// Forward Message
//
// Receive Example
// [toUserID, text] [2, "Hello, World!"]
//
// Send Example
// [fromUserID, text] [1, "Hello, World!"]
webSocket.on('message', function(message) {
console.log('received from ' + userID + ': ' + message)
var messageArray = JSON.parse(message)
var toUserWebSocket = webSockets[messageArray[0]]
if (toUserWebSocket) {
console.log('sent to ' + messageArray[0] + ': ' + JSON.stringify(messageArray))
messageArray[0] = userID
toUserWebSocket.send(JSON.stringify(messageArray))
}
})
webSocket.on('close', function () {
delete webSockets[userID]
console.log('deleted: ' + userID)
})
})
Instructions
To test it out, run npm install
to install ws
. Then, to start the chat server, run node server.js
(or npm start
) in one Terminal tab. Then, in another Terminal tab, run wscat -c ws://localhost:5000/1
, where 1
is the connecting user's user ID. Then, in a third Terminal tab, run wscat -c ws://localhost:5000/2
, and then, to send a message from user 2
to 1
, enter ["1", "Hello, World!"]
.
Shortcomings
This chat server is very simple.
Persistence
It doesn't store messages to a database, such as PostgreSQL. So, the user you're sending a message to must be connected to the server to receive it. Otherwise, the message is lost.
Security
It is insecure.
If I know the server's URL and Alice's user ID, then I can impersonate Alice, ie, connect to the server as her, allowing me to receive her new incoming messages and send messages from her to any user whose user ID I also know. To make it more secure, modify the server to accept your access token (instead of your user ID) when connecting. Then, the server can get your user ID from your access token and authenticate you.
I'm not sure if it supports a WebSocket Secure (
wss://
) connection since I've only tested it onlocalhost
, and I'm not sure how to connect securely fromlocalhost
.