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.
Related
I'm setting up a simple chat server with NodeJS that only uses a server and client. It works, and I can open up multiple client windows on the same machine, but now I need a bit more.
I would like to:
Give each client the option to set usernames
Have a client request current time from server
Action commands like "/me punches the warlock" that the server shows others as "User punches the warlock"
This sounds like a quick days work, but I just started looking at UDP and I can't quite find any examples online other than a generic server/client thing that sends and gets messages. How would I go about those tasks?
Code:
Server.js:
var dgram = require('dgram'); //import datagram to get everything needed for UDP
var PORT = 22222;
var CLIENT_PORT = 2223;
// An IP address that's reserved on each network
// Gets sent to the server
var ADDRESS = "-"; //dont want to show my IP :)
var sock = dgram.createSocket({reuseAddr: true, type: 'udp4'}); //can now open multiple clients
var current_time = Date.now(); //?
function sendMessage(data) {
sock.send(data, 0, data.length, PORT, ADDRESS, function(err){
if(err){
throw err;
}
});
}
sock.on("message", function(data, rinfo) {
//listen for messages and print them
console.log(data);
//Check if the client's port was equal to the port to find client data on
//If so, get packet
if (rinfo.port === CLIENT_PORT) {
console.log('\nreceived');
//call function to broadcast the data out to everyone on the local network
sendMessage(data);
}
//Get the string data from the data buffer.
var stringData = data.toString(); //also could be toJSON()
console.log(stringData);
//Convert that string back into a buffer by making a new Buffer and passing it in.
//The buffer class can take a string, an array or just a number of bytes to allocate to memory
var backToBuffer = new Buffer(stringData); //can take a string, array or just a size to allocate
console.log(backToBuffer);
});
//This opens the connection and starts listening
//(Client Port, Address to listen to which is ALL, What to do)
sock.bind(CLIENT_PORT, '', function(){
sock.setBroadcast(true);
console.log('listening on port ' + PORT + "\n");
});
Client.js:
var dgram = require('dgram');
var SERVER_PORT = 22222;
var PORT = 22223;
var ADDRESS = "-";
//read input from the command line
var stdin = process.stdin;
var stdout = process.stdout;
var sock = dgram.createSocket({reuseAddr: true, type: 'udp4'});
var server_sock = dgram.createSocket({reuseAddr: true, type: 'udp4'});
function sendMessage(data) {
//onsole.log("sending data");
sock.send(data, 0, data.length, PORT, ADDRESS, function(err) {
if(err) {
throw err;
}
//nsole.log("sent");
});
}
server_sock.on("message", function(data, rinfo) {
console.log("received " + data.toString());
});
server_sock.bind(SERVER_PORT, '', function() {
console.log('listening to server port');
});
sock.bind(PORT, '', function() {
sock.setBroadcast(true);
console.log("please enter a message\n");
stdin.resume();
stdin.on("data", function(data) {
sendMessage(data);
});
});
Node.js has loads of libraries to make realtime communication chats, I don't understand the choice of using UDP and managing everything by yourself, and it also looks that you are not very expert on this. My suggestion is to use a websocket library like it can be socket.io which they even have an example of a simple chat in their website http://socket.io/get-started/chat/
Using socket.io (or similar) it will help you a lot since it has sessions so you can save the username and return it everytime you post a message.
Below I wrote a small example of the server side (took from the index.js of the get-started above).
io.on('connection', function(socket){
var username = 'RANDOM';
socket.on('chat message', function(msg){
//here you should catch messages starting with "/" and parse them to write a different message
io.emit('chat message', username + ': ' msg);
});
socket.on('update username', function(msg) {
username = msg;
io.emit('username changed', username);
});
});
I hope it helps.
I have a very simple configuration in a node server with socket.io installed (a little bit more complex but essentially like this one):
var main = require('express')();
server = require('http').createServer(main);
io = require('socket.io')(server);
io.use(function(socket, next) {
console.log("middleware!");
next();
});
io.on('connection', function (socket) {
console.log('connected...');
socket.on('pong', function (data) {
console.log(data.message);
});
setTimeout(function() {
console.log("Saying hello");
socket.emit('ping', { message: 'Hello from server ' + Date.now() });
}, 1000);
});
server.listen(2080, function onCreateServerMain() {
console.log('Server main is listening on port 2080';
console.log('************************************************************');
});
In the client:
var socketIoScript,
loadSocketTimeout,
trialsToLoadSocketIo = 0,
APP_CFG = {baseUrl : "http://192.168.1.13:2080"};
function loadSocketIo(socketIoIp) {
socketIoScript = document.createElement('script');
socketIoScript.setAttribute('src', socketIoIp);
socketIoScript.setAttribute('onload', 'onSocketLoaded();');
document.head.appendChild(socketIoScript);
}
window.onSocketLoaded = function onSocketLoaded() {
if (typeof(io.connect) === 'function') {
var mSocket,
mIoSocket;
$timeout.cancel(loadSocketTimeout);
mIoSocket = new io.Manager(APP_CFG.baseUrl);
mIoSocket.connect(function(socket) {
console.log('Connected!!');
});
mIoSocket.on('error', function onSocketError(e) {
console.log('WebSocket Error ' + error);
});
mIoSocket.on('ping', function onPingReceived(e) {
console.log('Server emitted ping: ' + e.data);
mSocket.emit('pong', 'hi server!');
});
}
}
~(function onLoadSocketTimeout() {
var nextTimeout;
if (trialsToLoadSocketIo < 10) {
nextTimeout = 5000;
} else if (trialsToLoadSocketIo > 60) {
nextTimeout = 60000;
} else {
nextTimeout = 1000 * trialsToLoadSocketIo;
}
if (socketIoScript) {
document.head.removeChild(socketIoScript);
}
loadSocketIo(APP_CFG.baseUrl + '/socket.io/socket.io.js#' + trialsToLoadSocketIo);
loadSocketTimeout = $timeout(onLoadSocketTimeout, nextTimeout);
trialsToLoadSocketIo += 1;
})();
(I'm doing like this because it's mobile app so it may have not connection). I'm testing it with Brackets and Chrome. Server and client are in the same machine. In the app the script is loaded fine and it connects to the server as I can it see in node log (edit: and this is all what I get in the node console):
Server main is listening on port 2080
************************************************************
middleware!
connected...
Saying hello
Edit: in Chrome console I don't get any message, and any breakpoint stops at on listeners. If I stop node, the console for the Chrome immediately starts logging that it has been disconnected:
GET http://192.168.1.13:2080/socket.io/?EIO=3&transport=polling&t=1413066902601-6 net::ERR_CONNECTION_REFUSED
GET http://192.168.1.13:2080/socket.io/?EIO=3&transport=polling&t=1413066906606-7 net::ERR_CONNECTION_REFUSED
But I can't see any incoming message. In the app I don't receive any incoming message. Is there any reason why I could not communicate in this environment even if socket is successfully connected?
EDIT
No app is receiving events sent from the other side. Logs from node show this, logs from Chrome are empty.
EDIT
In Chrome app I don't receive console.log("Connected!");. But neither I receive ERR_CONNECTION_REFUSED errors: I don't receive anything.
EDIT
I managed to get console.log("Connected!"); in the app by changing Manager options:
mIoSocket = new io.Manager(APP_CFG.baseUrl, { autoConnect: false });
As it was auto connecting and the events were attached after connection was made, "Connected" was never reached. But I'm still not receiving any event in any app.
I had a similar issue were event callbacks on the server were not firing when emitting. My event names were ping and pong. As soon as I renamed these events everything worked.
I suspect the event names ping and pong are reserved by socket.io and so cannot be used.
Ok, so a few things :
First, var mSocket doesn't seem to be initialized, so it may be difficult for it to emit() anything (am I missing something?)
Second, when you do :
socket.on('pong', function (data) {
console.log(data.message);
});
the server expects to receive an object containing a message property, eg : data = {message:'hi server'} In your case, you send a string, so data is 'Hi server !' and your log will say 'undefined'. You should change this bit to :
socket.on('pong', function (data) {
console.log(data);
});
and you have a similar problem the other way around, you send an object : { message: 'Hello from server ' + Date.now() }, and are trying to log a data property which does not exist. Change this bit to :
console.log('Server emitted ping: ' + e.message);
And third , you have to listen for events on the socket, not the 'manager'
Client :
mIoSocket.connect(function(socket) {
console.log('Connected!!');
socket.emit('pong');
socket.on('error', function onSocketError(e) {
console.log('WebSocket Error ' + error);
});
socket.on('ping', function onPingReceived(e) {
console.log('Server emitted ping: ' + e.data);
socket.emit('pong', 'hi server!');
});
});
Server :
io.on('connection', function (socket) {
console.log('connected...');
socket.on('pong', function (data) {
console.log(data);
});
setTimeout(function() {
console.log("Saying hello");
socket.emit('ping', { message: 'Hello from server ' + Date.now() });
}, 1000);
});
I'm attempting to write a small relay script in node.js that listens for incoming TCP connections on a local socket, and when it gets one, forwards the traffic to a 3rd party. It must also take any returned data from that 3rd party and send it back to the original local socket. I've tried code like http://delog.wordpress.com/2011/07/19/a-tcp-relay-mechanism-with-node-js/ and it does work, but it requires the sender be a server that is listening on a socket itself, and my utility is intended to work with any program that tries to create an outbound TCP connection. Unfortunately, the problem I'm running into is that everything works great the first time with the client sending the data to the "router" program, and the router forwarding it to another server, and then returning the data from the client. However, when the client program ends or is terminated and attempts to reconnect, I get this:
events.js:72
throw er; // Unhandled 'error' event
^
Error: This socket has been ended by the other party
at Socket.writeAfterFIN [as write] (net.js:275:12)
at Socket.<anonymous> (/root/tcp_loop.js:37:17)
at Socket.emit (events.js:117:20)
at Socket.<anonymous> (_stream_readable.js:748:14)
at Socket.emit (events.js:92:17)
at emitReadable_ (_stream_readable.js:410:10)
at emitReadable (_stream_readable.js:406:5)
at readableAddChunk (_stream_readable.js:168:9)
at Socket.Readable.push (_stream_readable.js:130:10)
at TCP.onread (net.js:528:21)
I ripped out all of the logic and distilled the test case into a small bit of code: one server that acts as both the router (listening on port 8124) as well as the "remote" server (on port 9999), though my testing indicates it makes no difference weather the remote server is on the same machine, on the Internet, etc. Here is the server code:
var net = require('net'),
util = require('util')
;
// The loop_server simulates a remote service.
// The error occurs whether using it here, or actually forwarding
// the data to a remote host.
var loop_server = net.createServer(function(loop) {
console.log("Loop server connected");
loop.on("end", function() {
console.log("Loop server disconnected");
});
loop.on("data", function(data) {
console.log("Loop got data: " + data);
loop.write(data);
});
}).listen(9999, function() {
console.log("Loop server bound");
});
var remote_socket = net.connect(9999, function() {
console.log("Remote connected");
var local_server = net.createServer(function(local_socket) { //'connection' listener
console.log('Local server connected');
local_socket.on('end', function() {
console.log('Local server disconnected');
// local_socket.destroy();
});
local_socket.on('data', function(ldata) {
console.log("Local socket got data: " + ldata);
remote_socket.write(ldata);
});
remote_socket.on('data', function(rdata) {
console.log("Remote socket got data: " + rdata);
local_socket.write(rdata);
});
local_socket.write('hello\r\n');
}).listen(8124, function() { //'listening' listener
console.log('Local server bound');
});
}); // remote_socket
The thing that's failing is the local_socket.write(rdata); in the remote_socket.on('data', ... handler. It works the first time the router is started and the client connects, but never again.
For reference, here is the code for the little client app that I've been using. I get the same result with a perl script, telnet, etc.:
var net = require('net');
var client = new net.Socket();
client.connect(8124, function() {
console.log('CONNECTED TO: localhost:8124');
client.write('Single text message from the client app');
});
client.on('data', function(data) {
console.log('DATA: ' + data);
});
client.on('close', function() {
sconsole.log('Connection closed');
});
Any insight would be greatly appreciated. I feel like I must be missing something extremely simple here...
Update:
Nitzin's solution below is a better way to do this, but in my particular example below, the solution is to remove old remote_socket.on('data') listeners before creating new ones, e.g.:
var remote_socket = net.connect(9999, function() {
console.log("Remote connected");
var local_server = net.createServer(function(local_socket) { //'connection' listener
console.log('Local server connected');
remote_socket.removeAllListeners('data');
...
remote_socket.on('data', function(rdata) {
console.log("Remote socket got data: " + rdata);
local_socket.write(rdata);
});
You should not destroy the socket. It closes both ends of the socket. You should only .end() it, which closes your writing end.
EDIT
Destroying the socket is bad, as I originally wrote, but your real problem is something completely different: you got your proxy (what you call "local") and echo (what you call "remote") servers backwards: the proxy server should make a new connection to the echo server for each new connection the proxy server gets, not the other way around as you have it now.
The only end() needed is in the client, to let the server know you're done writing.
Here is client.js:
var net = require('net');
var client = new net.Socket();
client.connect(8124, function() {
console.log('CLIENT: CONNECTED: localhost:8124');
client.write('single text message from the client app');
client.end();
});
client.on('data', function(data) {
console.log('CLIENT: GOT DATA: ' + data);
});
client.on('close', function() {
console.log('CLIENT: CONNECTION CLOSED');
});
And here is servers.js:
var net = require('net'),
util = require('util');
net.createServer(function(conn) {
console.log('ECHO_SERVER: CONN: new connection');
conn.on('end', function() {
console.log('ECHO_SERVER: CONN: disconnected');
});
conn.on('data', function(data) {
console.log('ECHO_SERVER: CONN: GOT DATA: ' + data);
conn.write(data);
});
}).listen(9999, function() {
console.log('ECHO_SERVER STARTED');
});
net.createServer(function(conn) {
console.log('PROXY_SERVER: CONN: new connection');
var remote = net.connect(9999, function() {
console.log('PROXY_SERVER: CONNECTED TO ECHO_SERVER');
conn.on('end', function() {
console.log('PROXY_SERVER: CONN: disconnected');
remote.end();
});
conn.on('data', function(data) {
console.log('PROXY_SERVER: CONN: GOT DATA FOR ECHO_SERVER: ' + data);
remote.write(data);
});
remote.on('data', function(data) {
console.log('PROXY_SERVER: CONN: GOT DATA FROM ECHO_SERVER: ' + data);
conn.write(data);
});
});
}).listen(8124, function() {
console.log('PROXY_SERVER STARTED');
});
As you can see, for each conn to the proxy server, there is a new remote going to the echo server.
I've got a litte problem with my code snipet. I wrote a example to learn the TCP Socket Communication for a project. For the moment i can send a TCP Socket and read the answer, but i want to use the answer in other software parts. For that i tried to use the variable socketmessage but this doesn't work. Does anyone have the answer for my problem? Thanks a lot
var net = require('net');
var client = new net.Socket();
var HOST='127.0.0.1';
var PORT='20000';
var MSG="{\"REQUEST\":\"STATUS\"}";
var socketmessage;
socketmessage=getSocketMessage(MSG);
console.log ("Socket Message: " + socketmessage);
function getSocketMessage(tcpmsg){
var outData;
client.connect(PORT, HOST, function() {
console.log("Client: " + tcpmsg);
client.write(tcpmsg);
});
client.setTimeout(5000, function() { client.destroy(); });
client.on('data', function(data) {
console.log('Server: ' + data);
outData = data.toString('utf8');
console.log ("Socketmessage: " + outData);
client.destroy();
});
//Add a 'close' event handler for the client socket
client.on('close', function() {
console.log('Connection closed');
});
// Add a 'error' event handler for the client socket
client.on('error', function(error) {
console.log('Error Connection: ' + error);
});
return outData;
}
Terminal:
Socket Message: undefined
Client: {"REQUEST":"STATUS"}
Server: {"STATUS":0.000000}
This is because function getSocketMessage is asynchronous. You are trying to return the received message. The function returns immediately, outData being undefined then. Its value is
set when data arrives from server. The network I/O is evented, the event you use is data
client.on('data', function(data) {
The received message can only be handled properly inside the event-handler for data. You would have to call your other part from here itself.
You can create a read stream and once the stream ends you may process the data.
var readStream = fs.createReadStream(path of the file, 'utf8'); //you can use path.join(loc, filename)
var data = '';
readStream.on('data', function(chunk:any) {
data += chunk;
}).on('end', function() {
let gotContent = data.toString(); //
doWhatEver(gotContent) //the method is async or promose
then(function(result){
console.log(result); //desired output
})
});
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();
});