Nodejs: This socket is closed - node.js

I am using tcp sockets in Node.js to communicate with a Java client.
See my very basic server implementation below:
var server = my_http.createServer();
echo.installHandlers(server, {
prefix: '/echo'
});
server.listen(8000, '0.0.0.0');
var socketServer = net.createServer(function (socket) {
// Identify this client
socket.name = socket.remoteAddress + ":" + socket.remotePort
// Put this new client in the list
clients.push(socket);
sockets[socket.name] = socket;
// Handle incoming messages from clients.
socket.on('data', function (data) {
try {
var obj = JSON.parse(data);
if (obj.type == "sendMessage") {
broadcast("{\"id\":\"1\", \"msg\": \"" + obj.msg + "\", \"name\": \"" + obj.name + "\", \"time\": \"" + getDateTime() + "\"}\n", socket);
}
} catch (er) {
}
});
// Remove the client from the list when it leaves
socket.on('end', function () {
try {
clients.splice(clients.indexOf(socket), 1);
} catch (err) {
}
});
// Send a message
function broadcast(message, sender) {
try {
clients.forEach(function (client) {
client.write(message); // ERROR IS HERE
});
} catch (ee) {
}
}
return socket;
}).listen(8080);
For some reason sometimes i get this error:
events.js:71
throw arguments[1]; // Unhandled 'error' event
^
Error: This socket is closed.
Its happening on this line:
client.write(message); // ERROR IS HERE
Any ideas how to prevent this from happening?

or use client.writable to detect if the socket available.
clients.forEach(function (client) {
try {
if (client.writable) {
clientwrite("are u alive");
} else {
console.log('client is not writable');
}
} catch (err) {
console.log("cannot send message.");
}
}

Try this code
Option1
function broadcast(message, sender) {
try {
clients.forEach(function (client) {
if(client._handle){ // ensure there is still underlying handle
client.write(message); // ERROR IS HERE
}
});
} catch (ee) {
}
}
Option2
Attach error event listener on socket.
Socket.on('error',function(){
console.log("%j", arguments);
});

Related

Node.js call parent method in class

I am trying to emit an event inside a class.
But I can't find a way to call the parent method.
Please see the comment lines to understand what I'm trying to do.
This is my VirtualChart.js
var WebSocketClient = require('websocket').client;
const EventEmitter = require("events");
class VirtualChart extends EventEmitter {
constructor() {
super();
this.client = new WebSocketClient();
this.client.on('connectFailed', function(error) {
console.log('Connect Error: ' + error.toString());
});
this.client.on('connect', function(connection) {
console.log('WebSocket Client Connected');
connection.on('error', function(error) {
console.log("Connection Error: " + error.toString());
});
connection.on('close', function() {
console.log('echo-protocol Connection Closed');
});
connection.on('message', function(message) {
if (message.type === 'utf8') {
console.log("Received: '" + message.utf8Data + "'");
this.emit("newMessage", message.utf8Data);//here is the problem
//this.parent.emit("newMessage", message.utf8Data);??????
//this.parent.parent.emit("newMessage", message.utf8Data);??????
}
});
});
this.client.connect('wss://myurl.com');
}
}
And this is my main.js
var VirtualChart = require('./VirtualChart');
var virtualChart = new VirtualChart();
virtualChart.on("newMessage", (param) => {
console.log("newMessage " + param);
});
Well, I do see one problem. The value of this in this.emit() is probably wrong because it is set by the connection.on() handler and will not point to your object. You can fix that my using an arrow function for your callback instead of a plain function.
Change this:
this.client.on('connect', function(connection) {
console.log('WebSocket Client Connected');
connection.on('error', function(error) {
console.log("Connection Error: " + error.toString());
});
connection.on('close', function() {
console.log('echo-protocol Connection Closed');
});
connection.on('message', function(message) {
if (message.type === 'utf8') {
console.log("Received: '" + message.utf8Data + "'");
this.emit("newMessage", message.utf8Data);
}
});
});
to this (which uses arrow functions for the callbacks):
this.client.on('connect', connection => {
console.log('WebSocket Client Connected');
connection.on('error', error => {
console.log("Connection Error: " + error.toString());
});
connection.on('close', () => {
console.log('echo-protocol Connection Closed');
});
connection.on('message', message => {
if (message.type === 'utf8') {
console.log("Received: '" + message.utf8Data + "'");
this.emit("newMessage", message.utf8Data);
}
});
});
The arrow functions will preserve the lexical value of this. The regular function(...) callbacks will not and the value of this will be set by the caller of the callback (which knows nothing about your object).

nodejs-serialport => RE-Establish connection to port after closed

Accordding to my last question SerialPort 'close' event never fire. I was unabled to detected if the COM is disconnected so I have created my own way to detect it.
I have created timestamp, and checked it with interval() every 1 sec to see if it is connected.
when it's detect the COM is unplugged I have try to re-establish the connection or re-instance port with SerialPort like you'll see inside the code below.
When it's try to reconnect I've get Error: Access denied.
There is a way to refresh or clean the cache? , because I think the server still hold the connection when isn't closed propely.
I've also tried port.close() and it's throw me out: Error: Port is not open.
var comPort = '\\\\.\\COM7',
lastDataTime,
lastresult,
count = 0,
lastDataTime,
comStatus,
error;
var port = new SerialPort(comPort, function (err) {
if (err) {
comStatus = false;
return console.log('Error: ', err.message);
}
});
const parser = port.pipe(new Readline());
port.on('open', function () {
console.log('~Port is open.');
parser.on('data', function (data) {
comStatus = true;
lastDataTime = Date.now();
if (++count == 10) {
count = 0;
lastresult = data;
}
});
});
setInterval(function () {
if (Date.now() - lastDataTime > 1000 || !comStatus) {
comStatus = false;
port.close();
port = new SerialPort(comPort, function (err) {
if (err) {
error = 'Error: ' + err.message;
return console.log(error);
}
});
}
}, 1000);
app.get('/', function (req, res) {
res.send((comStatus) ? lastresult : 'Disconnected - ' + error);
console.log(lastresult);
})
Thanks!
As you can see in /node_modules/serialport/lib/serialport.js: close-event may not be emitted (unlike disconnect).
You can add console.log locally like below to simple debug.
P.S. I tested it on Win7x32. Close-event is emitted.
SerialPort.prototype._disconnected = function(err) {
this.paused = true;
this.emit('disconnect', err);
// add: console.log('1', this.closing);
if (this.closing) {
return;
}
// add: console.log('2', this.fd);
if (this.fd === null) {
return;
}
this.closing = true;
if (process.platform !== 'win32') {
this.readable = false;
this.serialPoller.close();
}
// add: console.log('3');
SerialPortBinding.close(this.fd, function(err) {
// add: console.log('4', this._events.close.toString());
this.closing = false;
if (err) {
debug('Disconnect close completed with error: ', err);
}
this.fd = null;
this.emit('close'); // it's your target
}.bind(this));
};
Reconnect example
var SerialPort = require('serialport');
var port = new SerialPort('COM1', {autoOpen: false, baudRate: 9600});
function open () {
port.open(functon (err) {
if (!err)
return;
console.log('Port is not open: ' + err.message);
setTimeout(open, 10000); // next attempt to open after 10s
});
}
port.on('open', function() {
function send() {
if (!port.isOpen()) // v5.x require
return console.log('Port closed. Data is not sent.');
port.write(123, function (err) {
if (err)
console.log('Error on write: ' + err.message)
port.drain(() => console.log('DONE'));
});
}
setInterval(send, 1000);
});
port.on('close', function () {
console.log('CLOSE');
open(); // reopen
});
port.on('data', (data) => console.log('Data: ' + data));
port.on('error', (err) => console.error('Error: ', err.message));
open(); // open manually
According to the serialport.io,
The resume() method causes an explicitly paused, Readable stream to
resume emitting 'data' events, switching the stream into flowing mode.
Simply, when port is closes, serialport library emits a close event
serialport.on('close', function(error){
if(error.disconnected === true){
console.log("disconnected");
}
}
, which will allow us whether port is disconnected or not.
That means the disconnected port is not available to re-establish the connection again, so you have to use serialport.resume() method to re-enable the connection.
serialport.on('close', function(err){
console.log("Port closed.");
if(err.disconnected === true){
console.log("Disconnected!");
serialport.resume(function(e){
reconnectDevice(); // Serial Port Initialization Function. It's your method to declare serial port.
console.log("Error on resuming port:", e);
});
}
});
After that, it will automatically switch COM ports and you won't get error as 'Port Access denied.'.

Need only one connection with RbbitMQ for the node application, not for every publish call

Whenever I publish new message it create one new connection. I want to have only one connection and one channel for all the publich calls.
Read from the rabbitmq website:
Some applications need multiple connections to an AMQP broker. However, it is undesirable to keep many TCP connections open at the same time because doing so consumes system resources and makes it more difficult to configure firewalls. AMQP 0-9-1 connections are multiplexed with channels that can be thought of as "lightweight connections that share a single TCP connection".
But how???
Here is my Code:
Channel.js
var amqp = require('amqplib/callback_api');
var url = process.env.AMQP_URL || 'amqp://guest:guest#localhost:5672';
module.exports = createQueueChannel;
function createQueueChannel(queue, cb) {
console.log("connecting................");
amqp.connect(url, onceConnected);
function onceConnected(err, conn) {
if (err) {
console.error('Error connecting:', err.stack);
}
else {
console.log('connected');
conn.createChannel(onceChannelCreated);
}
function onceChannelCreated(err, channel) {
if (err) {
cb(err);
}
else {
channel.assertQueue(queue, {durable: true}, onceQueueCreated);
}
function onceQueueCreated(err) {
if (err) {
cb(err);
}
else {
cb(null, channel, conn);
}
}
}
}
}
Publish.js
var Channel = require('./channel');
var queue = 'queue';
Channel(queue, function(err, channel, conn) {
if (err) {
console.error(err.stack);
}
else {
console.log('channel and queue created');
var work = 'Do some work';
channel.sendToQueue(queue, encode(work), {
persistent: true
});
// setImmediate(function() {
// channel.close();
// conn.close();
// });
}
});
function encode(doc) {
return new Buffer(JSON.stringify(doc));
}
Define your connection (amqpConn) and publisher channel (pubChannel) outside the publish function, and use that channel when you are publishing a message.
I recommend you to take a look at the full example code here: https://gist.github.com/carlhoerberg/006b01ac17a0a94859ba
(https://www.cloudamqp.com/blog/2015-05-19-part2-2-rabbitmq-for-beginners_example-and-sample-code-node-js.html)
Where also an offline queue is used in case the connection is down for a while.
var amqpConn = null;
function start() {
amqp.connect(process.env.URL + "?heartbeat=60", function(err, conn) {
if (err) {
console.error("[AMQP]", err.message);
return setTimeout(start, 1000);
}
conn.on("error", function(err) {
if (err.message !== "Connection closing") {
console.error("[AMQP] conn error", err.message);
}
});
conn.on("close", function() {
console.error("[AMQP] reconnecting");
return setTimeout(start, 1000);
});
console.log("[AMQP] connected");
amqpConn = conn;
whenConnected();
});
}
And when connected, you start the publisher.
function whenConnected() {
startPublisher()
}
var pubChannel = null;
var offlinePubQueue = [];
function startPublisher() {
amqpConn.createConfirmChannel(function(err, ch) {
if (closeOnErr(err)) return;
ch.on("error", function(err) {
console.error("[AMQP] channel error", err.message);
});
ch.on("close", function() {
console.log("[AMQP] channel closed");
});
pubChannel = ch;
while (true) {
var m = offlinePubQueue.shift();
if (!m) break;
publish(m[0], m[1], m[2]);
}
});
}
And the publish function like:
function publish(exchange, routingKey, content) {
try {
pubChannel.publish(exchange, routingKey, content, { persistent: true },
function(err, ok) {
if (err) {
console.error("[AMQP] publish", err);
offlinePubQueue.push([exchange, routingKey, content]);
pubChannel.connection.close();
}
}
);
} catch (e) {
console.error("[AMQP] publish", e.message);
offlinePubQueue.push([exchange, routingKey, content]);
}
}

Return value, or stop script

Helo,
i create API in Windows Azure Mobile service, In this api script i have function to connect the other service. I have problem how to return value or stop executable my script when i have good answer from service. Function process.exit(1), don't work.
function function1(item,response) {
var buf ='';
var net = require('net');
var HOST = 'xxxx.xxxx.xxxx.xxxx';
var PORT = xxx;
var client = new net.Socket();
client.setTimeout(100000, function() {
console.log("Timeout");
response.send(500, "Timeout");
});
client.connect(PORT, HOST, function() {
client.write(item + "\n");
client.on('data', function(data) {
buf = buf + data.toString('utf-8');
});
client.on('close', function() {
});
client.on('end', function() {
if (buf.length > 1) {
var result = JSON.parse(buf);
//if resulr.Aviable is true the functios should return result or send result and stop execiuting script
if ( result.Avaiable) {
response.send(200, result);
//now i wont't to respond answer to client or return my value(result)
console.log('Send data');
}
}
client.destroy();
});
});
}
One alternative is to have a flag which indicates whether a response has been sent or not. This way, when the first of the alternatives is reached, you can set the flag to true (possibly clearing the timeout so it doesn't linger more than it needs) and in all cases check whether the flag has been set before returning the response. Something along the lines of the code below:
function function1(item,response) {
var buf = '';
var net = require('net');
var HOST = 'xxxx.xxxx.xxxx.xxxx';
var PORT = xxx;
var client = new net.Socket();
var responseSent = false;
var timeoutHandler = client.setTimeout(100000, function() {
if (!responseSent) {
responseSent = true;
console.log("Timeout");
response.send(500, { error: "Timeout" });
}
});
client.connect(PORT, HOST, function() {
client.write(item + "\n");
client.on('data', function(data) {
buf = buf + data.toString('utf-8');
});
client.on('close', function(had_error) {
if (!responseSent) {
clearTimeout(timeoutHandler);
responseSent = true;
console.log('Socket closed');
response.send(500, { error: had_error ? 'Socket error' : 'unknown' });
}
});
client.on('end', function() {
if (!responseSent) {
responseSent = true;
clearTimeout(timeoutHandler);
if (buf.length > 1) {
try {
var result = JSON.parse(buf);
if (result.Available) {
response.send(200, result);
} else {
response.send(500, { error: 'Socket data is not available' });
}
} catch (ex) {
response.send(500, { error: 'error parsing JSON', exception: ex });
}
} else {
// We should always return a response
response.send(500, { error: 'No data read from socket' });
}
}
client.destroy();
});
});
}
Notice that since node.js runs on a single thread, you can assume that there will be no cases where the response is sent twice. Also, you should make sure that the response is always sent once - in the code you had, if there was a socket error, or if buf.length was not greater than 1, or if result.Avaiable was not true, then the timeout response would be sent, but you didn't need to wait for the whole (100 seconds) time to send that response.

Connecting Unity3d with Node.js

I am trying to use socket.io to connect my unity3d program with node.js server.
Using the UnitySocketIO, I succeeded the connection between the client and server.
However, On or Emit method does not work.
Can someone help me with this problem?
void Start () {
string socketUrl = "http://127.0.0.1:50122";
Debug.Log("socket url: " + socketUrl);
this.socket = new Client(socketUrl);
this.socket.Opened += this.SocketOpened;
this.socket.Message += this.SocketMessage;
this.socket.SocketConnectionClosed += this.SocketConnectionClosed;
this.socket.Error += this.SocketError;
this.socket.Connect();
}
private void SocketOpened (object sender, EventArgs e) {
Debug.Log("socket opened"); // i got this message
this.socket.On ("message", (data) => {
Debug.Log ("message : " + data);
});
this.socket.Emit("join", "abc");
Debug.Log("Emit done"); // i got this message
}
....
io.sockets.on('connection', function (socket) {
console.log('connect'); // i got this message
socket.emit('message', 'Hello World!');
socket.on('join', function (id) {
console.log('client joined with id ' + id);
socket.emit('message', 'Hello ' + id);
});
});
Your event probably attached in wrong order, try like this:
void Start() {
string socketUrl = "http://127.0.0.1:50122";
Debug.Log("socket url: " + socketUrl);
this.socket = new Client(socketUrl);
this.socket.Opened += this.SocketOpened;
this.socket.Message += this.SocketMessage;
this.socket.SocketConnectionClosed += this.SocketConnectionClosed;
this.socket.Error += this.SocketError;
this.socket.On("message", (data) => {
Debug.Log("message: " + data);
});
this.socket.Connect();
}
And for node:
io.sockets.on('connection', function(socket) {
console.log('client connected');
socket.emit('message', 'Hello World!');
});
As well do not allow client to decide own ID, as it is "hackable" in most cases. Only server should make important decisions and not client.

Resources