I am trying to learn to use NodeJS and JavaScript to replace at least some of my Perl code.
I need to create a socket and have a server/listener accept data sent from a client.
The problem I am having is that under Windows 2012 server, the listener code below just completely ignores the socket.on command, but it works fine under CentOS.
Does anyone have any suggestions as to what I am missing?
var net = require('net');
var fs = require('fs');
var server = net.createServer(function(socket) {
console.log('At : ' + (new Date()) + '\nA client connected to server...');
console.log('IP addr : ' + socket.remoteAddress);
// Process data sent from client
socket.on('data', function(data) {
console.log('Reached socket.on function.\n');
// Following command reads the data stream from client
var string = ('IP addr : '+ socket.remoteAddress + ' sent on ' + (new Date()) + ' : ' + data.toString()+'\n');
console.log(string);
// Following command writes the data stream to a file
fs.appendFile('client-data', string, function(err) {
if (err) {
return console.log(err);
}
console.log('Data saved from client...');
});
});
// This section sends data back to client, close socket, and
// resets to accept new socket connection
socket.write('\n<svrdata>\nData received by : HS-AD02 \r\n</svrdata>');
socket.pipe(socket);
socket.end();
console.log('The client has disconnected...\n');
}).listen(10337, 'hs-ad02');
In the code above the problem has a very simple solution.
Under Windows the two lines of
socket.pipe(socket);
socket.end();
Cause the socket to close prior to the receipt of the client data.
Removing those two lines and it works just fine.
Related
So I took the following code https://gist.github.com/tedmiston/5935757 example and modified it slightly such that the client writes data to the server. This should be doable since the client socket does support a write. In one of my use cases the client sends a fair amount of data from the client to server in which case I get an ECONNRESET error. Attached are client and server snippets. I was wondering if anyone has seen this and if they know what is going wrong under the covers.
Here is a copy of my client:
var net = require('net');
var client = new net.Socket({writeable: true}); //writeable true does not appear to help
client.on('close', function() {
console.log('Connection closed');
});
client.on('error', function(err) {
console.error('Connection error: ' + err);
console.error(new Error().stack);
});
client.connect(5900, '127.0.0.1', function() {
var count = 0;
console.log('Connected');
for(var i = 0; i < 100000; i++) {
client.write('' + i + '');
//bufferSize does not seem to be an issue
//console.info(client.bufferSize);
}
});
and my server:
var net = require('net');
var count = 0;
var server = net.createServer(function(socket) {
socket.pipe(socket); //With this uncommented I get an ECONNRESET exception after 14299 writes with it commented it hangs after 41020 writes
socket.on('data', function(data) {
console.info(count++); //This makes it occur sooner
//count++;
//maxConnections is not the issue
//server.getConnections(function(err, count) {
//console.info('count = ' + count);
//});
});
socket.on('close', function() {
console.info('Socket close');
});
socket.on('error', function(err) {
console.error('Socket error: ' + err + ', count = ' + count);
console.error(new Error().stack);
});
});
server.listen(5900, '127.0.0.1');
When the client has finished sending data in the for loop inside its connect event handler, there is nothing more for it to do so it exits. That terminates the connection, and the server gets an ECONNRESET to inform it that the connection has been broken.
If you want the client to hang around after it has finished sending then give it some reason to stay alive. Registering a data event handler on the client socket is one possibility.
I am working on an IoT project. With nodejs on heroku, i have created a server on heroku. Then my IoT device will try to establish a connection. But when i tried it, the connection automatically closes. Below is the script i am using. It is working locally.
net = require('net');
var clients = [];
net.createServer(function (socket) {
socket.name = socket.remoteAddress + ":" + socket.remotePort
clients.push(socket);
broadcast(socket.name + " joined the chat\n", socket);
socket.on('data', function (data) {
broadcast(socket.name + "> " + data, socket);
});
socket.on('end', function () {
clients.splice(clients.indexOf(socket), 1);
broadcast(socket.name + " left the chat.\n");
});
function broadcast(message, sender) {
clients.forEach(function (client) {
if (client === sender) return;
client.write(message);
});
process.stdout.write(message)
}
}).listen(process.env.PORT || 8899);
console.log("Chat server running at port 8899\n");
Please help.
I am also facing the same problem but I think the problem might be this
According to this article
If no data is received from the dyno within the 55 second window the
connection is terminated and an H15 error is logged.
Similarly, if no data is received from the client within the 55 second
window the connection is terminated an an H28 error is logged.
In node, when you create a socket server and connect to it with a client, the write function triggers the data event, but it seems there is no way to distinguish the source of the traffic (other than adding your own IDs/headers to each sent buffer).
For example, this is the output "server says hello" from the server.write, and then all of the "n client msg" are from client.write, and they all come out in on('data', fn):
➜ sockets node client.js
client connected to server!
client data: server says hello
client data: 1 client msg!
client data: 2 client msg!
client data: 3 client msg!
client data: 4 client msg!
Is there a correct way to distinguish the source of the data on a socket?
The code for a simple client:
// client.js
var net = require('net');
var split = require('split');
var client = net.connect({
port: 8124
}, function() {
//'connect' listener
console.log('client connected to server!');
client.write('1 client msg!\r\n');
client.write('2 client msg!\r\n');
client.write('3 client msg!\r\n');
client.write('4 client msg!\r\n');
});
client.on('end', function() {
console.log('client disconnected from server');
});
var stream = client.pipe(split());
stream.on('data', function(data) {
console.log("client data: " + data.toString());
});
and the code for the server
// server.js
var net = require('net');
var split = require('split');
var server = net.createServer(function(c) { //'connection' listener
console.log('client connected');
c.on('end', function() {
console.log('client disconnected');
});
c.write('server says hello\r\n');
c.pipe(c);
var stream = c.pipe(split());
stream.on('data', function(data) {
console.log("client data: " + data.toString());
});
});
server.listen(8124, function() { //'listening' listener
console.log('server bound');
});
The source of the traffic is the server.
If you're wanting to know whether it's data being echoed back to the client by the server, you will have to come up with your own protocol for denoting that.
For example, the server could respond with newline-delimited JSON data that is prefixed by a special byte that indicates whether it's an echo or an "original" response (or any other kind of "type" value you want to have). Then the client reads a line in, checks the first byte value to know if it's an echo or not, then JSON.parse()s the rest of the line after the first byte.
You can distinguish each client with:
c.name = c.remoteAddress + ":" + c.remotePort;
c.on('data', function(data) {
console.log('data ' + data + ' from ' + c.name);
});
I have a very simple TCP socket in Node.js. It connects to a device that sends data back in XML format. There is a C# program that does this same trick, but I had to build it in Node.js.
So, when the device sends a message, I'm getting the response about 5 seconds later! Where the C# program gets it 1 or 2 seconds later.
It looks like the 'tcp socket' has a specific polling frequency or some kind of 'wait function'. Is that even possible? Everytime an incoming message displays. It also display's the exit message of "sock.on('close')"
It seems that after 5 seconds the 'server' automaticly closes. See bottom lines "console.log('[LISTENER] Connection paused.');" After that, the incoming message gets displayed correctly.
What is wrong with my code?
// Set Node.js dependencies
var fs = require('fs');
var net = require('net');
// Handle uncaughtExceptions
process.on('uncaughtException', function (err) {
console.log('Error: ', err);
// Write to logfile
var log = fs.createWriteStream('error.log', {'flags': 'a'});
log.write(err+'\n\r');
});
/*
-------------------------------------------------
Socket TCP : TELLER
-------------------------------------------------
*/
var oHOST = '10.180.2.210';
var oPORT = 4100;
var client = new net.Socket();
client.connect(oPORT, oHOST, function() {
console.log('TCP TELLER tells to: ' + oHOST + ':' + oPORT);
// send xml message here, this goes correct!
client.write(oMessage);
});
// Event handler: incoming data
client.on('data', function(data) {
// Close the client socket completely
client.destroy();
});
// Event handler: close connection
client.on('close', function() {
console.log('[TELLER] Connection paused.');
});
/*
-------------------------------------------------
Socket TCP : LISTENER
-------------------------------------------------
*/
var iHOST = '0.0.0.0';
var iPORT = 4102;
// Create a server instance, and chain the listen function to it
var server = net.createServer(function(sock) {
// We have a connection - a socket object is assigned to the connection automatically
console.log('TCP LISTENER hearing on: ' + sock.remoteAddress +':'+ sock.remotePort);
// Event handler: incoming data
sock.on('data', function(data) {
console.log('Message: ', ' '+data);
});
// Event handler: close connection
sock.on('close', function(data) {
console.log('[LISTENER] Connection paused.');
});
}).listen(iPORT, iHOST);
client.write() does not always transmit data immediately, it will wait until buffers are full before sending the packet. client.end() will close the socket and flush the buffers.
You could try this: http://nodejs.org/api/net.html#net_socket_setnodelay_nodelay
Your 5 second delay does seem a bit weird, though.
So within the "TELLER" I had to write "sock.write(data);" inside the "sock.on('data', function(data)" event.
It works now. Thanks Jeremy and rdrey for helping me in the right direction.
I'm trying out node.js and socket.io. I wan't to use to remove a ping function I have to get updates from my server. Here is an example code of what I'm doing:
var app = require('http').createServer(),
io = require('socket.io').listen(app),
cp = require('child_process');
app.listen(8080);
//I check a global value for all the connected users from the php command line
var t = setInterval(function(){
cp.exec('/usr/bin/php /Users/crear/Projects/MandaFree/symfony api:getRemainingMessages',
function(err, stdout){
if (err) {
io.sockets.emit('error', 'An error ocurred while running child process.');
} else {
io.sockets.emit('change', stdout);
}
console.log('Remaining messages: ' + stdout);
});
}, 3000);
var remaining = io.of('/getRemainingMessages')
.on('connection', function(socket){
socket.on('disconnect', function(){});
});
The Issue here, is that when I call io.sockets.emit() the debug console tells me it is doing something, but it looks like it is not getting to the clients. Because they are doing nothing.
I use to have one interval for every connected client, and when I used socket.emit() it did worked. But it is not the optimal solution.
UPDATE:
Here is my client side code.
var remaining = io.connect('http://127.0.0.1:8080/getRemainingMessages');
remaining.on('change', function(data){
console.log('Remaining messages: ' + data );
$('#count').html(data);
});
remaining.on('error', function(error){
console.log(error);
});
Had a very similar issue couple of days back and looks like socket.io had some changes in the API. I have never worked with symfony and am hoping the issues are the same.
I have a working demo of socket.io sending and receiving a message - uploaded to https://github.com/parj/node-websocket-demo as a reference
Essentially two changes
On Server side - changed socket.on to socket.sockets.on
var socket = io.listen(server);
socket.sockets.on('connection', function(client)
On Client side - URL and port not required as it is autodetected.
var socket = io.connect();
This has been tested using Express 2.5.2 and Socket.io 0.8.7
I have amalgamated your server code with mine, would you be able to try this on the server and my client javascript and client html just to see if it is working?
var socket = io.listen(server);
socket.sockets.on('connection', function(client){
var connected = true;
client.on('message', function(m){
sys.log('Message received: '+m);
});
client.on('disconnect', function(){
connected = false;
});
var t = setInterval(function(){
if (!connected) {
return;
}
cp.exec('/usr/bin/php /Users/crear/Projects/MandaFree/symfony api:getRemainingMessages',
function(err, stdout){
if (err) {
client.send('error : An error ocurred while running child process.');
} else {
client.send('change : ' + stdout);
}
console.log('Remaining messages: ' + stdout);
});
}, 3000);
t();
});