How to retain the values across connections in websocket server? - node.js

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

Related

How to write a code to simulate the same as echo server from Websocket.org

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.

can't get response from websocket rxjs node Angular

Trying to get a WebSocket working using rxjs webSocket
I set up a node server, that throws no errors at the moment, but it doesn't send messages to the server or connected users
It seems to work better when I use 'ws://echo.websocket.org/', I see messages echoed back to me, however, I don't see messages sent, in other open browsers, basically no communication between users, that are supposed to be subscribed to the websocket
All I want is a simple way of carrying simple info between users
index.js
var express = require('express');
var WebSocketServer = require('websocket').server;
var app2 = express()//There is already another app var for main app server
var server2 = http.createServer(app2);
var server2 = app2.listen(8081, function () {
console.log((new Date()) + ' Server is listening on port 8081');
})
wsServer = new WebSocketServer({
httpServer: server2,
autoAcceptConnections: false
});
function originIsAllowed(origin) {
if (origin === 'http://localhost:1234'){
return true;
}
// put logic here to detect whether the specified origin is allowed.
}
wsServer.on('request', function(request) {
if (!originIsAllowed(request.origin)) {
// Make sure we only accept requests from an allowed origin
request.reject();
console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
return;
}
var connection = request.accept(null, request.origin);
console.log((new Date()) + ' Connection accepted.');
connection.on('message', function(message) {
// console.log(message)
if (message.type === 'utf8') {
console.log('Received Message from: ' + connection.remoteAddress);
connection.sendUTF(message.utf8Data);
}
else if (message.type === 'binary') {
console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');
connection.sendBytes(message.binaryData);
}
});
connection.on('close', function(reasonCode, description) {
console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
});
});
in my clientside socket service:
import { Injectable } from '#angular/core';
import { Observable } from '../../../node_modules/rxjs';
#Injectable()
export class SocketService {
socket$ = Observable.webSocket( 'ws://localhost:8081');
// 'ws://echo.websocket.org/'
constructor() {
this.connectToSocket()
}
connectToSocket(){
this.socket$.subscribe(
(message) => console.log('message received: ' + message),
(err) => console.log(err),
() => console.log('complete')
);
}
}
And to send message, from another component, I use:
this.socketService.socket$.next(JSON.stringify('test'))
According to the documentation of WebSocket-Node (https://github.com/theturtle32/WebSocket-Node/blob/master/docs/WebSocketServer.md), you have to programatically accept each connection before continuing the handshake.
You can instead set the autoAcceptConnections option of your server config to true, like this:
const wss = new WebSocketServer({ httpServer: server2, autoAcceptConnections: true });
If you do indeed have custom request checking requirements, you can use either accept or reject inside your request handler, like this:
request.accept('chosen-protocol', 'accepted-origin')
or
request.reject()

flash xml socket can connect to node.js 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

Socket.io communicating from server to client not happening

i am trying to do a very simple real time notification with socket.io. for some reason i can't receive data or fire the event from server to client but from client to server yes. let me show my code:
Client Side
ngOnInit() {
this.socket.on('connect', function (res: any) {
console.log('Socket.io is connected on client side!'); // it shows on client console
});
this.socket.on('alarmsreceived', function (res: any) {
console.log(res + ' i am here now'); // is not firing
});
}
// this method fires from a click button
objectStatus = () => {
this.socket.emit('alarmsystem', 'i am client going to server');
}
Server
var io = require('socket.io').listen(server);
var connections = [];
io.of('/api/v1/monitoring').on('connect', function(socket){
connections.push(socket);
console.log('Connected %s sockets', connections.length); // i see connection on cmd
socket.on('disconnect', function() {
connections.splice(connections.indexOf(socket), 1);
console.log('Connected %s sockets', connections.length);
});
socket.on('alarmsystem', function(res) {
console.log(res); // this shows me the message from client
io.sockets.emit('alarmsreceived', 'I am server heading to client');
});
})
it seems pretty straight forward, but not firing the client event. Can someone help me what i am doing wrong here? Thanks in advance

Node.js - Persistent connection adapter

My requirement is a little bit different, don't know even if it's achievable.
I am using Node.js for developing backend application server. This server basically does two jobs:
(1) Serving clients: My clients are all mobile phones who will be sending HTTP(S) request and after receiving the response will close the session.
(2) Calling some other asynchronously working service: The server, on the other hand, will be connected to some other server which works over just TCP/IP connection and not HTTP. Asynchronous here means, the server will send a request and should not wait for a response. The response will be received through same TCP/IP connection.
So the flow I want to achieve is:
Mobile phone sends the HTTP request to server
Server after receiving the HTTP request, does a call to service which is on TCP/IP
Server receives the response from TCP/IP service over the TCP/IP connection
Server responds to the phone with the response.
To represent the above flow I have attached the below image.
In the above image the TCP/IP Server is managed by some other provider.
I wrote the following code in node.js which works perfectly as per our requirement some times, but some times it sends incorrect response to the HTTP request. I did not write any code to handle this issue.
var net = require('net');
var client = new net.Socket();
client.connect(2202, 'example_ip', function () {
console.log('Connected');
// client.write('Hello, server! Love, Client.');
});
//Lets require/import the HTTP module
var http = require('http');
//Lets define a port we want to listen to
const PORT = 8080;
//We need a function which handles requests and send response
function handleRequest(request, response) {
var body = '';
request.on('data', function (chunk) {
body += chunk;
});
request.on('end', function () {
console.log('Received request from JMeter------------>>>');
// console.log(body);
client.write(body);
var count = 0;
client.on('data', function (data) {
console.log('<<<------------Received from SSM: ' + data);
response.end(data);
// client.destroy(); // kill client after server's response
});
});
client.on('close', function () {
console.log('Connection closed');
});
}
//Create a server
var server = http.createServer(handleRequest);
//Lets start our server
server.listen(PORT, function () {
//Callback triggered when server is successfully listening. Hurray!
console.log("Server listening on: http://localhost:%s", PORT);
});
Please some one guide me to solve this issue.
TCP streams don't work like WebSocket streams ( as you expect ). You need to use your own protocol to communicate with a TCP server. Keep in mind that HTTP clients are many and you have only one TCP connection to handle them, so use requestIds like below, code explains itself.
Not tested, but you can get the idea.
shared.js
exports.tcp = {
host: 'example_ip',
port: 2202
};
exports.http = {
host: 'localhost',
port: 8080
};
/**
* TCP "guarantees" that a receiver will receive the reconstituted
* stream of --> BYTES <-- as it was originally sent by the sender.
*
* eg. if written message = 'How are you today?'
* the messages can come to us as follows:
*
* 'How ar'
* 'e you '
* 'today?'
*
* so we need to use a simple protocol to handle messages
*/
exports.protocol = protocol;
function protocol(options) {
if (!options) options = {};
this.END_OF_MESSAGE = options.endOfMessage || '\0';
this.END_OF_PART = options.endOfPart || '\1';
this.dataBuffer = '';
}
protocol.prototype.packMessage = function(id, body) {
return [id, body].join( this.END_OF_PART ) + this.END_OF_MESSAGE;
};
protocol.prototype.unpackMessage = function(message) {
var parts = message.toString('utf8').split( this.END_OF_PART );
return {id: parts.shift(), body: parts.shift()};
};
protocol.prototype.extractMessages = function(data, callback) {
this.dataBuffer += data.toString('utf8');
if (this.dataBuffer.indexOf(this.END_OF_MESSAGE) !== -1)
{
var messages = this.dataBuffer.split(this.END_OF_MESSAGE);
var incomplete = this.dataBuffer.slice(-1) === this.END_OF_MESSAGE
? '' : messages.pop();
messages.forEach(function(message)
{
if (message !== '') {
callback( this.unpackMessage(message) );
}
});
this.dataBuffer = incomplete;
// rest of 'data'
}
/**
if (Buffer.byteLength(this.dataBuffer, 'utf8') > 10240) { // 10KB
console.log('[!] socket flooded');
this.dataBuffer = '';
}
*/
};
protocol.prototype.reset = function() {
this.dataBuffer = '';
};
httpServer.js
var http = require('http');
var net = require('net');
var shared = require('./shared.js');
var protocol = new shared.protocol();
var server = http.createServer(handleRequest);
server.listen(shared.http.port, shared.http.host, function() {
console.log('HTTP server listening: %s:%s', shared.http.host, shared.http.port);
});
function handleRequest(request, response) {
var body = '';
var requestId = nextId++;
var eventName = 'message' + requestId;
request.on('data', function(chunk) {
body += chunk.toString('utf8');
});
request.on('end', function()
{
// ref#2
client.write( protocol.packMessage(requestId, body) );
// ref#3
client.once(eventName, function(data) {
clearTimeout(timeoutId);
response.end(data);
});
});
var timeoutId = setTimeout(function() {
client.removeListener(eventName);
response.end('timeout');
}, 10000); // 10 sec.
/**
* [!] Don't do this; you are adding just another 'data' event to
* the TCP client for EVERY http request !?
*
* request: UNIQUE obj. for every http request
* client: a PERSISTENT (TCP) stream obj.
*
client.on('data', function() { });
**/
}
var client = new net.Socket();
// ref#1
client.connect(shared.tcp.port, shared.tcp.host, function() {
console.log('TCP conn. established to: ', shared.tcp.host, shared.tcp.port);
});
var nextId = 0;
// unique per http req.
/**
* [!] Do this ( once ) ( not for every request )
*/
client.on('data', function(data)
{
protocol.extractMessages(data, function(message) {
client.emit('message' + message.id, message.body);
// ref#3
});
});
client.on('close', function()
{
console.log('TCP conn. closed');
client.removeAllListeners();
})
client.on('error', function()
{
console.log('TCP conn. error', arguments);
// client.destroy(); // and reconnect here
});
tcpServer.js
var net = require('net');
var shared = require('./shared.js');
var protocol = new shared.protocol();
var server = net.createServer(handleConnection);
server.listen(shared.tcp, function() {
console.log('TCP server listening %s:%s', shared.tcp.host, shared.tcp.port);
});
// [!] CONNECTION handler ( ref#1 )
function handleConnection(client)
{
var this.dataBuffer = '';
// [!] DATA handler ( ref#2 )
client.on('data', function(data) {
protocol.extractMessages(data, function(message)
{
var requestId = message.id;
var body = message.body;
// Do whatever you want with 'body' here
/**
* And return back to 'client' with 'requestId' using same protocol again
* so the 'client' ( from httpServer.js ) can handle your response
*/
client.write( protocol.packMessage(requestId, body) );
});
});
}
Can you instantiate a new client for each incoming request? This way the TCP connection for each request will be unique.

Resources