I wrote a code for broadcasting a message to all users:
// websocket and http servers var webSocketServer = require('websocket').server; ... ... var clients = [ ]; var server = http.createServer(function(request, response) { // Not important for us. We're writing WebSocket server, not HTTP server }); server.listen(webSocketsServerPort, function() { ... }); var wsServer = new webSocketServer({ // WebSocket server is tied to a HTTP server. httpServer: server }); // This callback function is called every time someone // tries to connect to the WebSocket server wsServer.on('request', function(request) { ... var connection = request.accept(null, request.origin); var index = clients.push(connection) - 1; ...
Please notice:
array
.Goal: Let's say that the Node.js server wants to send a message to a specific client (John). How would the NodeJs server know which connection John has? The Node.js server doesn't even know John. all it sees is the connections.
So, I believe that now, I shouldn't store users only by their connection, instead, I need to store an object, which will contain the userId
and the connection
object.
Idea:
When the page finishes loading (DOM ready) - establish a connection to the Node.js server.
When the Node.js server accept a connection - generate a unique string and send it to the client browser. Store the user connection and the unique string in an object. e.g. {UserID:"6", value: {connectionObject}}
At client side, when this message arrives - store it in a hidden field or cookie. (for future requests to the NodeJs server )
When the server wants to send a message to John:
Find john's UserID in the dictionary and send a message by the corresponding connection.
please notice there is no asp.net server code invloced here (in the message mechanism). only NodeJs .*
Question:
Is this the right way to go?
With WebSockets: the server can send a message to the client without the client explicitly requesting something. the client and the server can talk to each other simultaneously. very little data overhead needs to be exchanged to send messages.
To send a message through the WebSocket connection you call the send() method on your WebSocket instance; passing in the data you want to transfer. socket. send(data); You can send both text and binary data through a WebSocket.
A server can open WebSocket connections with multiple clients—even multiple connections with the same client. It can then message one, some, or all of these clients. Practically, this means multiple people can connect to our chat app, and we can message some of them at a time.
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) }) })
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!"]
.
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 on localhost
, and I'm not sure how to connect securely from localhost
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With