I am trying to create a "rooms" like feature with the npm 'ws' package, similar to how rooms work in socket.io. I dont want to use socket.io, but cant figure out how to get information on the user/room at connection without sending an extra message.
I took this from the ws docs and it allows me to iterate through all the clients, but i would like to also differentiate a room?
import WebSocket, { WebSocketServer } from 'ws';
const wss = new WebSocketServer({ port: 8080 });
wss.on('connection', function connection(ws) {
// would like to add a user to a room here?
ws.on('message', function message(data) {
wss.clients.forEach(function each(client) {
if (client !== ws && client.readyState === WebSocket.OPEN) {
// only send to clients in the same room
}
});
});
});
This is the client side I have been using to test:
import WebSocket from 'ws';
const ws = new WebSocket('ws://localhost:8080');
ws.on('open', function open() {
ws.send(JSON.stringify({roomId: 1}));
});
ws.on('message', function message(data) {
console.log('received: %s', data);
});
If you are wanting to assign a room at connection you change the path of the url and then access it through the req object, then add it as a property on the connecting websocket.
Then you can send the roomId with any message and check that the roomId for message and the roomId for the client match before sending.
wss.on('connection', function connection(ws, req) {
ws.roomId = req.url;
ws.on('message', function message(data) {
const parsedMessage = JSON.parse(data);
wss.clients.forEach(function each(client) {
if (client !== ws && client.readyState === WebSocket.OPEN) {
if(client.roomId === parsedMessage.roomId){
ws.send(data);
}
}
});
});
});
In order to connect to this socket you would have to change your client to send to the url + the roomId.
const ws = new WebSocket('ws://localhost:8080/<put room id here>');
Without sending a second message this appears to get the functionality you are looking for
Related
how to emit the event with using particular_room [io.to(socket.id).emit('sendData') ]at cross domain
I've tried this,
server side
io.emit('sendData', data);
clientside
var socket = io('https://localhost:3000/', { transports: ['websocket'] });
socket.on('sendData', function (data) {
console.log(data);
})
above syntax are perfectly working on cross domain
but I want to emit with particular room at cross domain
io.to(socket.id).emit('sendData', data)
io.broadcast.to(socketid).emit('message', 'for your eyes only'); //sending to individual socketid
Reference link -> Cross-domain connection in Socket.IO
Kindly help to solve this!
I Understood your code, you just emit the initial connection on the socket.io server
io.on("connection", function(socket){
socket.emit('sendsocketid', data);
})
Cross-domain clientside
var socket = io('https://localhost:3000/', { transports: ['websocket'] });
var obj= [];
socket.on('sendsocketid', function (data) {
console.log(data);
// Now You Can Customize the or add the client Socket .id
var NewSocketid = {
id: socket.id
}
Obj.push(data, NewSocketid)
socket.emit("emitnewSocketId", Obj)
})
socket.on("emitnewSocketId", function(data){
consoleo.log(Obj[1].NewSocketid)
//Now You can emit the new socket id
io.to(Obj[1].NewSocketid).emit('sendData', data)
})
i need to create a server based on the same logic as the echo server on websocket.org.
The difference is that the server will not echo exactly what the user typed, but will return a response that varies with the received string.
I've been looking for more than a week and I only found n examples that only explain the client, some of which include an example of a server that does NOT answer wss:// calls.
Everything I found responds only to calls http://192.168.1.1:3000 or https://192.168.1.1:3000, but when I use wss: //192.168.1.1:3000, Firefox says, it was unable to establish a connection with the wss server: //192.168.1.1:3000/.
The client works when I call wss: //echo.websocket.org/.
Where do I find the code for an echo server that responds to wss?
Above I list the code I found on github. The nodejs server code I'm trying is:
const http = require('http');
const ws = require('ws');
const wss = new ws.Server({noServer: true});
console.log("Script has started");
if (!module.parent) {
console.log("Listening on port 3000");
http.createServer(accept).listen(3000);
} else {
exports.accept = accept;
}
function accept(req, res) {
console.log("accept event started");
// all incoming requests must be websockets
if (!req.headers.upgrade || req.headers.upgrade.toLowerCase() != 'websocket') {
console.log("This is no websocket!!! Return");
res.end();
return;
}
// can be Connection: keep-alive, Upgrade
if (!req.headers.connection.match(/\bupgrade\b/i)) {
res.end();
return;
}
console.log("Handle upgrade");
wss.handleUpgrade(req, req.socket, Buffer.alloc(0), onConnect);
}
function onConnect(ws) {
console.log("onConnect event started");
ws.on('message', function (message) {
let name = message.match(/([\p{Alpha}\p{M}\p{Nd}\p{Pc}\p{Join_C}]+)$/gu) || "Guest";
console.log("Send Hello");
ws.send(`Hello from server, ${name}!`);
setTimeout(() => ws.close(1000, "Bye!"), 5000);
});
}
This code, responds "This is no websocket!!! Return" if I call the server with http://192.168.1.1: 3000/
Thank you in advance.
After a while I found the solution:
// Basic Websocket (ws) echo server
const WebSocket = require('ws');
const ws_server = new WebSocket.Server({ port: 81 });
ws_server.on('connection', function connection(ws) {
console.log("A client connected");
ws.on('message', function incoming(message) {
ws.send('Hi, you sent me ' + message);
});
});
This works for my tests.
I would like to assign a unique identifier to each Websocket connection on the server side. I want to be able to access this identifier upon detecting that a socket close. I'm using the ws and nanoid
wss.on('connection', (ws, req) => {
ws.id = nanoid();
console.log(ws.id);
ws.on('close', (ws, req) => {
console.log(ws.id);
});
});
But unfortunately the second log in the close event listener prints undefined.
How do I maintain state of the WebSocket on the server side?
Thanks!
You just need to send msg to the available connections
try to add :
wss.clients.forEach(client => {
if(client !== ws && client.readyState === WebSocket.OPEN){
client.send(data)
}
})
I'm trying to create a simple chat application just for the challenge and to learn javascript even more.
For this, I use the built-in package net to do my socket server and client.
To do it simply , I have a client that send a Stringify object when it connect to the server and I want my server to send a message to every client currently connected.
This is the structure of my message :
socket.write(JSON.stringify({
type: message type,
data: message data,
author: message author
}))
Sorry for my bad english and thanks for everyone who read this.
You can do it like this. This is taken from the ws github page https://github.com/websockets/ws
There are many ways to achieve this but in Node this is probably the best solution.
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
// Broadcast to all.
wss.broadcast = function broadcast(data) {
wss.clients.forEach(function each(client) {
if (client.readyState === WebSocket.OPEN) {
client.send(data);
}
});
};
wss.on('connection', function connection(ws) {
ws.on('message', function incoming(data) {
// Broadcast to everyone else.
wss.clients.forEach(function each(client) {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(data);
}
});
});
});
Below is the websocket server side code that uses "ws" plugin.
var WebSocketServer = require('ws').Server
,wsSend = new WebSocketServer({port: 8080}) //Client sends message on this port.
,wsReceive = new WebSocketServer({port: 8081}) //Response is sent on this port.
,clientMessage;
wsSend.on('connection', ReceiveSocketConnection);//From client.
//Callback function on connection with client.
function ReceiveSocketConnection(webSocket) {
webSocket.on('message', GetMessageFromClient);
}
//Handler to receive message from client.
function GetMessageFromClient(messageFromClient) {
clientMessage = messageFromClient; //Message from client saved into variable
}
wsReceive.on('connection', SendSocketConnection);//To client.
function SendSocketConnection(webSocket) {
webSocket.send(clientMessage);//Here clientMessage is undefined
}
Below is the client side code.
var WebSocket = require('ws')
, wsSend = new WebSocket('ws://localhost:8080') //send port
, wsReceive = new WebSocket('ws://localhost:8081'); //receive port
//Open connection on send port.
wsSend.on('open', function() {
wsSend.send('Hi I am new to websockets');
});
//Open connection on receive port.
wsReceive.on('open', function() {
//Do nothing
});
//Receive message from server via port 8081
wsReceive.on('message', function(message) {
console.log('received: %s', message);
});
Separate ports for sending and receiving messages are there because it is a design decision.
I want to echo the message by receiving it on one port and sending it on another.
Problem : The message from the client is not saved into the local variable(i.e clientMessage).Any suggestions?
this should work, however i recommend using http://socket.io/
var WebSocketServer = require('ws').Server
,wsSend = new WebSocketServer({port: 8080}) //Client sends message on this port.
,wsReceive = new WebSocketServer({port: 8081}) //Response is sent on this port.
wsReceive.broadcast = function(data) {
for(var i in this.clients)
this.clients[i].send(data);
};
wsSend.on('connection', function(ws) {
ws.on('message', function(message) {
console.log('received: %s', message);
try {
console.log('sending: %s', message);
wsReceive.broadcast(message);
} catch (e) {
console.log(e);
}
});
});