node.js websocket crashes when client disconnect - node.js

I am very new to NodeJS and Websockets, but i am trying to play with it.
What i do is read incoming datas from Serial port, then send these datas to a web page using websocket.
From here everything works fine.
I use node-static to serve my web page
I use ws for websocket
The problem is when a client close his browser, then my NodeJS websocket server crashes with the following error :
root#WS-SERVER-2:~/app# node socketserver.js
open serial communication
Client disconnected.
/root/node-v0.10.29/lib/node_modules/ws/lib/WebSocket.js:187
else throw new Error('not opened');
^
Error: not opened
at WebSocket.send (/root/node-v0.10.29/lib/node_modules/ws/lib/WebSocket.js:187:16)
at sendAll (/root/app/socketserver.js:30:16)
at SerialPort.<anonymous> (/root/app/socketserver.js:58:8)
at SerialPort.emit (events.js:95:17)
at Object.module.exports.raw [as parser] (/root/node-v0.10.29/bin/node_modules/serialport/parsers.js:8:13)
at Object.SerialPort.options.dataCallback (/root/node-v0.10.29/bin/node_modules/serialport/serialport.js:143:15)
at SerialPortFactory.SerialPort._emitData (/root/node-v0.10.29/bin/node_modules/serialport/serialport.js:312:20)
at afterRead (/root/node-v0.10.29/bin/node_modules/serialport/serialport.js:290:18)
at /root/node-v0.10.29/bin/node_modules/serialport/serialport.js:304:9
at Object.wrapper [as oncomplete] (fs.js:459:17)
Here is my websocket/serialport code :
var WebSocketServer = require('../node-v0.10.29/lib/node_modules/ws').Server;
var SerialPort = require('../node-v0.10.29/bin/node_modules/serialport').SerialPort;
var serialPort;
var portName = '/dev/ttyACM0';
var sendData = "";
var wss = new WebSocketServer({port: 8080});
var CLIENTS=[];
wss.on('connection', function(ws) {
CLIENTS.push(ws);
ws.on('message', function(message) {
console.log('received: %s', message);
sendAll(message);
});
ws.on('close', function() {
console.log('Client disconnected.');
});
ws.on('error', function() {
console.log('ERROR');
});
ws.send("");
});
function sendAll(message)
{
for(var i=0;i<CLIENTS.length;i++)
{
CLIENTS[i].send(message);
}
}
serialListener();
function serialListener(debug)
{
var receivedData = "";
serialPort = new SerialPort(portName, {
baudrate: 9600,
dataBits: 8,
parity: 'none',
stopBits: 1,
flowControl: false
});
serialPort.on("open", function () {
console.log('open serial communication');
// Listens to incoming data
serialPort.on('data', function(data) {
receivedData += data.toString();
if (receivedData .indexOf('E') >= 0 && receivedData .indexOf('B') >= 0) {
sendData = receivedData .substring(receivedData .indexOf('B') + 1, receivedData .indexOf('E'));
receivedData = '';
}
// send the incoming data to browser with websockets.
sendAll(sendData);
});
});
}
Can someone help me to figure out what's wrong here ?

I think, you should remove the socket from your CLIENTS array on both close and error event. Otherwise it tries to send a message to a socket that is closed.

I was having this same issue. Turned out I was attempting to send events to sockets that were in the "closing" state. Checking that each socket was specifically open before broadcasting a message fixed it for me:
function sendAll(data){
for(var i = 0; i < clients.length; i++){
if(this.clients[i].readyState != this.clients[0].OPEN){
console.error('Client state is ' + this.clients[i].readyState);
}
else{
this.clients[i].send(data);
}
}
}

Try this while sending data to client:
- socket is my current web socket object.It overwrites the default >WebSocket.js class condition that throws "not-opened error".
if (socket.readyState != socket.OPEN) {
console.error('Client state is ' + socket.readyState);
//or any message you want
} else {
socket.send(JSON.stringify(object)); //send data to client
}

Related

NodeJS net module - don't try to create another instance of TCP server when called again

I'm totally new to the whole nodeJS asynchronous-y callback-y programming so I need more like a guidance to understanding what I'm even doing. With that said, I have two files main.js and server.js
My main file looks like this:
var server=require('./server.js');
server();
function WhenUserClicksButton(){
server();
}
and my server file looks like this:
var net = require('net');
function server(){
net.createServer(function (socket) {
socket.write('\x16'); //SYN character
socket.on('data', function (data) {
//handle data from client
});
}).listen(33333);
}
First call of server(); starts the TCP server. Then function WhenUserClicksButton is called when user clicks button (duhh) in a GUI. But it attempts to start the server again so I get
Error: listen EADDRINUSE :::33333
I got why this is happening but I can't think of a solution for it. What I really need is:
Start the server and listen on 33333
When nothing is happening server and client just exchanges SYN and ACK characters every few seconds (I already have this part done, I just removed it from this example for clarity because it's not really topic of this question)
When user click button change socket.write('\x16'); to socket.write('something');
Then wait for server and client to exchange data and after everything is done return results back to main.js
As I said, I'm new to this and I believe my problem lies in not understanding fully of what I'm doing. Any help and explanations are welcome!
I think you're very near where you need to be. I would do something like this:
server.js
var net = require('net');
var netServer = null;
var netSocket = null;
function sendData(data) {
if (netServer && netSocket) {
console.log('Send data: sending: ', data);
netSocket.write(data);
}
}
function startServer(){
netServer = net.createServer(function (socket) {
netSocket = socket;
socket.write('\x16'); //SYN character
socket.on('data', function (data) {
console.log('Server: data from client: ', data);
if (data.length === 1 && data[0] === 0x16) {
// log and ignore SYN chars..
console.log('SYN received from client');
} else if (newDataCallback) {
newDataCallback(data);
};
});
});
console.log('Server listening on 33333..');
netServer.listen(33333);
}
var newDataCallback = null;
function setNewDataCallback(callback) {
newDataCallback = callback;
}
module.exports = {
sendData: sendData,
startServer: startServer,
setNewDataCallback: setNewDataCallback
};
main.js
var server = require('./server');
function newDataCallback(data) {
console.log('newDataCallback: New data from server: ', data);
}
server.setNewDataCallback(newDataCallback);
server.startServer();
function wheneverUserClicksButton() {
server.sendData('something');
}
testClient.js
var clientSocket = net.createConnection(33333, "127.0.0.1");
clientSocket.on('data', (someData) => {
console.log('Data received', someData);
});
clientSocket.on('connect', () => {
console.log('Client Socket connected ');
clientSocket.write('Hello from client');
});

Simple Chat application with NodeJS [duplicate]

This question already has answers here:
socket.emit in a simple TCP Server written in NodeJS?
(3 answers)
Closed 5 years ago.
I am new to NodeJS and started to learn by building a simple command line chat application. I have the following code for Server and Client. Client-Server communication is successful but I am not able to capture 'adduser' event from the client. Please tell me where I am going wrong.
Server:
var net = require('net');
var chatServer = net.createServer(function(socket){
socket.pipe(socket);
}),
userName="";
chatServer.on('connection',function(client){
console.log("ChatterBox Server\n");
client.write("Welcome to ChatterBox!\n");
client.on('data',function(data){
console.log(""+data);
});
client.on('adduser',function(n){
console.log("UserName: "+ n);
userName = n;
});
});
chatServer.listen(2708);
Client:
var net = require('net');
var client = new net.Socket();
client.connect(2708,'127.0.0.1');
client.on('connect',function(){
client.emit('adduser',"UserName");
});
console.log("Client Connected!\n");
client.on('data',function(data){
console.log(""+data);
});
I guess you don't have to do from the client side :
client.connect(2708,'127.0.0.1');
Just write your client like this is sufficient.
var net = require('net');
var client = new net.Socket();
client.connect(2708, '127.0.0.1',function(){
console.log("Client Connected!\n");
client.emit('adduser',"UserName");
});
client.on('data',function(data){
console.log(""+data);
});
client.on('close', function() {
console.log('Connection closed');
});
So the server side :
var net = require('net');
var sockets = [];
var port = 2708;
var guestId = 0;
var server = net.createServer(function(socket) {
// Increment
guestId++;
socket.nickname = "Guest" + guestId;
var userName = socket.nickname;
sockets.push(socket);
// Log it to the server output
console.log(userName + ' joined this chat.');
// Welcome user to the socket
socket.write("Welcome to telnet chat!\n");
// Broadcast to others excluding this socket
broadcast(userName, userName + ' joined this chat.\n');
socket.on('adduser',function(n){
console.log("UserName: "+ n);
userName = n;
});
// When client sends data
socket.on('data', function(data) {
var message = clientName + '> ' + data.toString();
broadcast(clientName, message);
// Log it to the server output
process.stdout.write(message);
});
// When client leaves
socket.on('end', function() {
var message = clientName + ' left this chat\n';
// Log it to the server output
process.stdout.write(message);
// Remove client from socket array
removeSocket(socket);
// Notify all clients
broadcast(clientName, message);
});
// When socket gets errors
socket.on('error', function(error) {
console.log('Socket got problems: ', error.message);
});
});
// Broadcast to others, excluding the sender
function broadcast(from, message) {
// If there are no sockets, then don't broadcast any messages
if (sockets.length === 0) {
process.stdout.write('Everyone left the chat');
return;
}
// If there are clients remaining then broadcast message
sockets.forEach(function(socket, index, array){
// Dont send any messages to the sender
if(socket.nickname === from) return;
socket.write(message);
});
};
// Remove disconnected client from sockets array
function removeSocket(socket) {
sockets.splice(sockets.indexOf(socket), 1);
};
// Listening for any problems with the server
server.on('error', function(error) {
console.log("So we got problems!", error.message);
});
// Listen for a port to telnet to
// then in the terminal just run 'telnet localhost [port]'
server.listen(port, function() {
console.log("Server listening at http://localhost:" + port);
});
So you've got an object "users" inside the "user" when is connected, push user to the array users but you need to do (server side) on('close', ... to remove the user from users when connected is false ... etc

NodeJs net.Socket() events not firing

Trying to write a TCP client in Node v0.10.15 and I am having a little trouble getting data back from the server. I know that the server is working properly because I have 3-4 different clients written in different languages communicating with it.
Below is a snippet of a larger piece of code but this should get the point across.
The problem is: I'm expecting 2 packets coming back after writing to the socket (this part is not included in this example). I'm only seeing the "data" event being fired once. Is there something that I need to do to get node to resume reading from the Tcp stream? I can confirm that the server is sending 2 packets(The length and then the actual data) Any help would be appreciated.
var dc = require('./DataContracts.js');
var net = require('net');
require('buffertools').extend();
var client = net.Socket();
var isConnected = false;
var serverHost = '10.2.2.21';
var dataCallback;
var receivedBuffer = new Array();
function InitComm(buffer) {
if (!isConnected) {
client.connect(4987, serverHost, function() {
client.on('data', function(data) {
console.log('Received server packet...');
var buf = new Buffer(data);
receivedBuffer.push(buf);
client.resume();
});
client.on('end', function() {
if (receivedBuffer.length > 1) {
if (dataCallback !== undefined)
dataCallback(receivedBuffer);
}
});
client.on('close', function() {
//clean up
});
client.on('error', function(err) {
console.log('Error!: ' + err);
});
Communicate(buffer);
});
} else {
Communicate(buffer);
}
}
Turns out that node was combining both of the packets together. I must be missing a Carriage return on the first packet

Node restart UDP server

I'm creating a udp server for receiving a message and sending a response quickly.
I find myself, however, to have a problem: the server can not close the connection to the client once it has been answered.
So, to avoid saturating the server, I thought of a way to restart the server udp (a sort of re-bind), once a counter has reached a certain number, but I can not find a solution to close the server udp and restart it.
Is there a way to do this?
Here a code snippet example of what I have at the moment:
/** Udp server */
var reset = function() {
if(count > 3) {
server.close();
count = 0;
console.log('reset');
server.bind('4002');
}
return true;
};
var count = 0;
var server = require("dgram").createSocket("udp4");
server.on("message", function(message, requestInfo) {
count++;
message = message.toString();
if(message == null || message === '') {
reset();
return;
}
// do something with the received message and sends the reply ..
var response = new Buffer(result.toString());
server.send(response, 0, response.length, requestInfo.port, requestInfo.address);
reset();
}
);
server.on("error", function(error) {
console.log(error);
server.close();
});
server.on("listening", function() {
var address = server.address();
console.log("server listening " + address.address + ":" + address.port);
});
server.bind('4002');
This is the stack trace:
events.js:72
throw er; // Unhandled 'error' event
^
Error: Not running
at Socket._healthCheck (dgram.js:420:11)
at Socket.bind (dgram.js:160:8)
...

socket.io emit doesn't work in qupzilla

I've wrote a simple app and tested in Chrome. All works fine!
Now I'm testing with qupzilla, but when I trigger the .emit function, nothing happens!
From chrome i wrote a thing, the object is updated and sent to server, server does a broadcast. All fine (qupzilla receives the update too).
But, if I write something on qupzilla, this update isn't sent to server (No logs in node)
Here's some code.
Server side:
var io = require('socket.io').listen(8080);
io.set("log level", 1);
var dataStored = [];
io.sockets.on('connection', function (socket) {
socket.emit('event', dataStored);
socket.on('update', function (data) {
console.log(data);
dataStored = data;
socket.broadcast.emit("event", data);
});
});
And client side:
$scope.things = [];
$scope.pushingObj = "";
// socket
var socket = io.connect("http://localhost:8080", {
'connect timeout': 500,
reconnect: true,
'reconnection delay': 500,
'reopen delay': 500,
'max reconnection attempts': 10000
});
socket.on("event", function(data) {
$scope.things = data;
$scope.$apply();
});
//
$scope.pushObj = function() {
//console.log($scope.pushingObj);
$scope.things.push($scope.pushingObj);
socket.emit("update", $scope.things);
$scope.pushingObj = "";
}

Resources