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);
}
});
});
});
Related
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
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.
It's been a while since I've worked with Node and Websockets. Basically how do I get socket.send() to work from another function is what I'm stuck on.
const server = new WebSocket.Server({ port: 8080 });
server.on('connection', socket => {
socket.on('message', message => {
console.log(`received from a client: ${message}`);
});
socket.send('yo world!');
});
function onMessageHandler (target, context, msg, self) {
client.say(target, response);
server.socket.send(response);
console.log(response);
}
}
How do I get my onMessageHandler to trigger a socket send, this is fail... server.socket.send(response);
Seeing your question i think there is a lack of understanding on how Websockets work. I am assuming you're using https://github.com/websockets/ws
There are two things. First is the WebSocketerver which you've named as server and then an Individual Socket which you've named as socket
Now the thing to understand is socket is not accessible outside server.on() callback The reason for this is there could be 1000 of sockets connected at a given instance and there would be no way to uniquely identify a particular socket you want to send message to.
So ask yourself the question that your application wants to send message to an individual socket to send to everyone who is connected to your server (basically broadcast)
If you want to send to an individual, you will have to uniquely identify the user
this._wss = new WebSocket.Server({
port: ENV_APP_PORT_WS
});
this._wss.on("connection", async (ws: AppWebSocket, req: IncomingMessage) => {
// const ipAddress = req.connection.remoteAddress; // IP Address of User
logger.info(req);
const queryParams = url.parse(req.url, true).query;
let authUser: User;
try {
authUser = await this._authenticateWebSocket(queryParams);
} catch (e) {
// Terminate connection and return...
}
// WS User INIT
ws.isAlive = true;
ws.userId = authUser.id;
ws.uuid = Helpers.generateUUIDV4();
ws.send(JSON.stringify({
type: "connected",
env: ENV
}));
});
The above code will add a property to each socket object that will enable it to uniquely identify a particular user/socket.
While sending =>
onMessageHandler(targetUserId: number, message: string) {
const allSockets = <AppWebSocket[]>Array.from(this._wss.clients.values());
const targetSocket = allSockets.find(w => w.userId === targetUserId);
targetSocket.send(message);
}
If You want to send to all connect users, it's quite easy:
https://github.com/websockets/ws#server-broadcast
Currently having an issue with "Broadcast" not seeming to function properly with a super simple websocket setup I started in Node. This is my first time working with websockets so I may be missing something pretty apparent, but after looking online for a while I wasn't able to find a resolution.
Basically I am just trying to have the ability to push some json out to all currently connected Clients.
I can confirm that that socket is working because I am able to see the static connection string on 'ws.send' in the 'connection' block when I connect at ws://localhost:3000, as well as seeing mulitple clients logged out from the broadcast method if I connect with multiple clients.
Any help as to what I may be missing would be greatly appreciated,
var WebSocketServer = require('uws').Server;
var wss = new WebSocketServer({ port: 3000 }); // ws://localhost:3000
// Static test var
var test_message = {
'test': 'Response',
'test2': 'Response2'
};
// Broadcast to all.
wss.broadcast = function broadcast(data) {
wss.clients.forEach(function each(client) {
console.log('IT IS GETTING INSIDE CLIENTS');
console.log(client);
// The data is coming in correctly
console.log(data);
client.send(data);
});
};
wss.on('connection', function(ws) {
ws.on('message', function(message) {
wss.broadcast(test_message);
console.log('Received: ' + message);
});
// TODO This is static just to check that the connection is properly working
ws.send('You successfully connected to the websocket.');
});
I tested your code with Smart Websocket Client. Your code is fine. If you broadcast data having string only, then you can see the reply in UI, but for javascript object, the client doesn't display although you can see response as Binary Frames (opcode = 2) in Chrome Developer Tools.
The reason behind this behavior is that the ws.send() method support normal strings, typed arrays or blobs, but sending typed arrays and blobs will result in the frame(s) received by the client as binary frames (opcode = 2).
You can try JSON.stringify the object,
wss.on('connection', function(ws) {
ws.on('message', function(message) {
wss.broadcast(JSON.stringify(test_message));
console.log('Received: ' + message);
});
ws.send('You successfully connected to the websocket.');
});
am connecting xml socket to node.js websocket. Its showing connect message first. When a message send to server, its showing socket close error.
import flash.net.XMLSocket;
var client_socket: XMLSocket = new XMLSocket();
client_socket.connect("localhost",8080);
client_socket.addEventListener(DataEvent.DATA, on_serverData);
client_socket.addEventListener(Event.CONNECT, on_serverConnection);
client_socket.addEventListener(IOErrorEvent.IO_ERROR,IOerror);
client_socket.addEventListener(Event.CLOSE,socketclose);
client_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR,socketsecurityerror);
function socketsecurityerror(event:SecurityErrorEvent)
{
trace("socketsecurityerror");
}
function IOerror(event : IOErrorEvent):void
{
trace("IOerror");
}
function socketclose(event : Event):void
{
trace("socketclose");
}
function on_serverConnection(event:Event)
{
trace("connected");
var o :Object= new Object();
o.hello = "initial_start" ;
// client_socket.send(JSON.stringify(o));
}
function on_serverData(event:DataEvent)
{
trace("errorrrrrrrrrr"+event.target.data);
}
What could be the issue, as its showing connect message and socketclose error only while sending data to websocket.
The below code is my websocket server.
var WebSocketServer = require('ws').Server
, wss = new WebSocketServer({ port: 8080 });
wss.on('connection', function connection(ws)
{
ws.on('message', function incoming(message) {
});
ws.on('close', function() {
});
ws.on('error', function() {
});
});
Will it be an issue with xmlsocket and websocket communication?
Thanks
XMLSocket cannot connect to a Websocket.
Websockets have a handshake and a protocol (see https://www.rfc-editor.org/rfc/rfc6455), whereas XMLSocket is just for sending and receiving XML data.
If you want to use websockets in AS3, try something like https://github.com/theturtle32/AS3WebSocket