Manage multiple TCP socket nodejs - node.js

I have an array like this:
var exports = module.exports = {};
var net = require('net');
exports.config = [
{
ip: "127.0.0.1",
id: 1,
socket: new net.Socket(),
data: "",
},
{
ip: "192.168.5.242",
id: 2,
socket: new net.Socket(),
data: "",
}
];
I'm trying to connect each of this items with a TCP socket with this code:
for(var key in tornelli.config) {
tornelli.config[key].socket.connect(4000, tornelli.config[key].ip, function() {
console.log('CONNECTED TO: '+tornelli.config[key].ip);
});
tornelli.config[key].socket.on('data', function(data) {
...........
});
tornelli.config[key].socket.on('error', function(error){
console.log(error);
});
}
But somethings get wrong because in the console output I get
CONNECTED TO: 192.168.5.242
But actually I'm connected with '127.0.0.1'. It seems that I don't separate each tcp stream. How can I have two separate tcp stream, one every item in this array?
It's somethings about asynchronous execution?
Thanks

In Javascript, for loops are not "blocks". You can put var in there if you want but it will still be "hoisted" to the top of your function. Everything is fine in your initial function calls - key will be 0, and then 1, and the loop will run twice. But when the CALLBACKS are executed, key will always be 1 - its last value. The callbacks are asynchronous, so they will be fired well after the for loop has done its thing.
Javascript has a forEach operator that makes tasks like this simpler. Try the following (or simply break out your socket-handling code to a function that takes the config block as a parameter):
tornelli.config.forEach(function(config) {
config.socket.connect(4000, config.ip, function() {
console.log('CONNECTED TO: '+config.ip);
});
config.socket.on('data', function(data) {
...........
});
config.socket.on('error', function(error){
console.log(error);
});
}
For what it's worth, it's also really unusual to pre-create things like sockets inside config files. A more standard pattern would be to do the new net.Socket() call inside the above code, not in the config file.

Related

Node.js Net Sockets: Can't connect to multiple IP's

i want to readout data from 2 diffrent IP adresses. But i always get "EALREADY" Error.
Which means that the Socket is "already in use", although i'm destroying the socket after i received the data.
If i remove the for loop and only readout 1 adress, it works just fine...
If i'm adding timeouts they won't fire... and i don't know why either.
var socket = new net.Socket();
var test = [];
test[0] = '10.5.0.5';
test[1] = '10.5.0.11';
for(var i=0;i<test.length;i++) {
socket.connect('2711', test[i], function() {
socket.write('d\n');
console.log("1");
console.log(test[i]);
socket.on('data', function(data) {
data = data.toString();
console.log(data);
socket.destroy();
console.log("2");
});
});
}
Help highly appreciated.
Thanks in advance.
The "For loop" is synchronous but ".connect" and ".on('data'" are asynchronous, therefore the for loop finished before the first connection happens. The second connection attempt happens when first one is still in progress, that is why you get connection error.
You should try a recursive function, advancing step by step. For example I create a function that receives an array, and iterate the first element of array, connect, and on data close it and call again the function if array still has more items.
var socket = new net.Socket();
var test = [];
test[0] = '10.5.0.5';
test[1] = '10.5.0.11';
function testIP(test){
socket.connect('2711', test.shift(), function() {
socket.write('d\n');
console.log("1");
socket.on('data', function(data) {
data = data.toString();
console.log(data);
socket.destroy();
console.log("2");
if( test.length > 0 ){
testIP(test);
}
});
}
testIP(test);
Bonus: There are libraries in Node.js to work with asynchronous tasks

React and Socket.io: Able to get initial data - but view doesn't update when a new post comes in

Not sure if the issue is how I have my sockets setup - or if I am incorrectly trying to render the data with React.
I can successfully pull in data with my socket - yet it doesn't live update state when new data is posted to the server. My intention is for the state in React to automatically render new data, which is always live because of the socket connection.
Here is my client app that gets messages from the server and renders them:
var Chat = React.createClass({
getInitialState: function() {
return {
messages: null
}
},
componentWillMount: function(){
var self = this;
socket.emit('getMessages');
socket.on('serverMessages', function (data) {
self.setState({messages: data})
});
},
render: function() {
var messages = this.state.messages ? <MessageList messages={this.state.messages}/> : null
return (
<div className="jumbotron">
{ messages }
<MessageForm submitMessage={this.submitMessage}/>
</div>
);
}
});
Just in case here is my server code that emits data:
io.on('connection', function (socket) {
socket.on('getMessages', function (data) {
Message.find(function(err, messages){
socket.emit('serverMessages', messages);
})
});
});
As of right now, you're "just" grabbing data from the server once the component has been loaded. To get something a bit more "real time" you'll want to either ping the server with the same emit statement you specified regularly (which defeats the point of using websockets, really, you could use long-polling) or have the server regularly send new data to all clients.
You can do EITHER:
A) Client side: "Polling" for information [Not Ideal]
Note: I initially put this in my answer because I saw the OP was "polling" when the controller was loaded. I didn't click on that this might be because the controller may not be loaded with the websocket so sending data on connect might not work here. My bad.
Replace socket.emit('getMessages') with something that will "poll" the websocket regularly for data:
setInterval(function () {
socket.emit('getMessages')
}, 10000); /* Request data from the socket every 10 seconds */
OR
B) Server side: Send new data as it becomes available. [Best Way]
Track all clients via a clients array and delete them from it when their session ends.
var clients = [];
io.on('connection', function (socket) {
clients.push(socket);
socket.on('end', function () {
// Could also splice the array below, but it still works.
delete clients[clients.indexOf(socket)];
});
/* Previous logic for server goes here */
});
Run this code when you need to push new messages from the database/data storage:
for (var i in clients) {
clients[i].emit('serverMessages', /* messages object */);
}
Your server code is only firing upon initial socket connection.
Server:
socket.on('getMessages', function (data) {
Message.find(function(err, messages){
socket.emit('serverMessages', messages);
})
});
Client:
var Chat = React.createClass({
getInitialState: function() {
return {
messages: null
}
},
componentWillMount: function(){
var self = this;
socket.emit('getMessages');
socket.on('serverMessages', function (data) {
self.setState({messages: data})
});
},
render: function() {
var messages = this.state.messages ? <MessageList messages={this.state.messages}/> : null
return (
<div className="jumbotron">
{ messages }
</div>
);
}
});
Based on naming convention, it also appears that your Message.find() is pulling a single message. I would recommend clarifying the labeling to match cardinality.
Try this:
var Chat = React.createClass({
getInitialState: function() {
return {
messages: null
}
},
componentWillMount: function(){
var self = this;
socket.emit('getMessages');
socket.on('serverMessages', function (data) {
self.setState({messages: data})
});
},
render: function() {
var messages = this.state.messages ? <MessageList messages={this.state.messages}/> : null
return (
<div className="jumbotron">
{ messages }
<MessageForm submitMessage={this.submitMessage}/>
</div>
);
}
});
Could it be possible its due to the componentWillMount lifecycle method? Could you try the componentDidMount instead.
It looks like render will see the state update but only gets executed once despite the state change according to facebook.

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

Code not terminating

I am using twitter API in my code and mongodb. The is reflecting the correct output in database, but it's not terminating. I guess the problem is with db.server.find({id:myid},cb); statement in code below. However, I don't know how to work it out.
var Twit = require('../lib/twitter'),
conf = require('../config1');
var myid;
var twit = new Twit(conf);
var databaseUrl = "mydb2"; // "username:password#example.com/mydb"
var collections = ["server", "followers"];
var db = require("mongojs").connect(databaseUrl, collections);
twit.get('account/verify_credentials', function (err, reply) {
myid = reply.id;
function addToServer(myid, cb) {
db.server.find({
id: myid
}, cb);
};
addToServer(myid, function (err, resp) {
if (err) {
console.log("err");
} else if (resp.length > 0) {
console.log("My Id present in server present");
} else {
console.log("New to the app.So updating server ");
db.server.insert({
id: myid
});
db.followers.insert({
id: myid,
following: []
})
}
});
});
P.S: This is a part of my code , I have also used process.exit(0) function, but still no help.
I think your issue is related to this: https://github.com/mafintosh/mongojs/issues/15.
Here's a gist. If I call db.close() the program exists, and if I don't, it doesn't. So process.on('exit') must not be the right place to call it.
But the issue is that that you have a persistent tcp connection open to the DB, and as long as that's running, the script won't shut down.
Is this a run-once script, or do you need to keep this thing running?
EDIT:
Since the script only needs to run once, I'd use callbacks on your 2 database queries and close the database down in the last callback.

Node.js: module system, object references

// connections.js
...
module.exports = {
conn: {
mongodb: {
connect: function() {throw ...},
disconnect: function() {throw ...},
getState: function() {throw...}
},
mysql: {
connect: function() {throw ...},
disconnect: function() {throw ...},
getState: function() {throw ...}
}
},
drivers: {
mongoose: mongoose,
mysql: mysql
},
states: connectionStates,
setup: function(config, cb) {
// provides concrete implementations of connect(), discconnect(),
// getState(), sets up listeners to relay connection events
this.conn.mongodb = setupMongo(config.mongodb);
this.conn.mysql = setupSql(config.mysql);
...
cb();
}
};
Now if I include this as:
// main.js
var connections = require(__dirname + '/connections'),
conn = connections.conn,
db = conn.mongodb;
// connectionections.setup() not been called yet
exports.foo = function() {
// connections.setup() already been called before this point
db.connect(...); // fails - error thrown - using the abstract function
conn.mongodb.connect(...); // works
}
Why does the first one fail? The db var should contain a reference to connections.conn.mongodb? At very least, I'd expect both to either work, or not work. What is the difference that allows the first to fail and second to succeed? Thank you
Its failing in the first case because setup() was called in a different scope and db/conn.mongodb diverged (with a copy on write) when setup was called. If you compare db and conn.mongodb in the exports.foo function, you should see that conn.mongodb has been initialized with the setupMongo and db still has the uninitialized versions. Not sure what the code looks like that is calling connections.setup, but from the looks of this, db !=== conn.mongodb.

Resources