Bug in sending multiple 2-D Arrays through socket.io - javascript

I am noticing a bug in socket.io. I am sending multiple (5) 2-D Array's through socket.io. All of the Array's are coming through, at different lengths/sizes and at different times, if that matters with how node.js or socket.io handle them. But they are seperate so I didn't think it mattered, just mentioning.
I have the incoming data from another source that populates Array1, Array2....ect. Here are some examples of what's happening, when sending through socket.io.
When I send test1: test1 does populate on the client side.
When I send test2: test2 does not populate on the client side.
when I send test2, then test1: test1 and test2 populate on the client side.
var Array1 = [];
var Array2 = [];
var Array3 = [];
var Array4 = [];
var Array5 = [];
jsonResults = JSON.stringify({
'test1': Array1,
'test2': Array2,
'test3': Array3,
'test4': Array4,
'test5': Array5
});
Just for an example of how I am calling variables on the client side
var socket = io.connect();
socket.on('message', function(message){
var obj = jQuery.parseJSON(message);
var value1 = obj.test1[1][1];
var value2 = obj.test2[0][5];
I have another question, If on the client side I call out a variable that doesn't exist like obj.test1[5][5] when test1 is only [4,5] sometimes it doesn't populate on the client side, for all the variables like test1[1][1] which does exist; Is there a particular reason for this or am I approaching this wrong?
Is there a better way to program this from .js side I have to handle multiple 2-D arrays of unknown size coming in at different times.
Server Side Listening to outside traffic.
// start UDP server listening on port 3001
udpRunningResultsServer.on("listening", function () {
var address = udpRunningResultsServer.address();
console.log("UDP Running Results Server listening on port: " + address.port);
console.log(" ")
});
udpRunningResultsServer.bind(3001);
// process datagram
udpRunningResultsServer.on("message", function (Runningmsg, Runninginfo) {
// check if datagram is full (size=536)
if(Runninginfo.size == 536){
tempRunningResults = tempRunningResults + Runningmsg.toString();
}
// datagram is not full, so this is the end of the message
else{
finalRunningResults = tempRunningResults + Runningmsg.toString();
RunningArray = finalRunningResults.split(';');
for (var a = 0; a < RunningArray.length; a++) {
var Runningtmp = RunningArray[a].length;
if (Runningtmp == 14 || Runningtmp == 0){
RunningArray.splice(a,1);
}
else {
RunningArray[a]= RunningArray[a].split(',');
}
}
RunningArray.unshift(time);
tempRunningResults ='';
}
});
// start UDP server listening on port 3002
udpShotPutWeightThrowResultsServer.on("listening", function () {
var address = udpShotPutWeightThrowResultsServer.address();
console.log("UDP Shotput/Weight Throw Server listening on port: " + address.port);
console.log(" ")
});
udpShotPutWeightThrowResultsServer.bind(3002);
// process datagram
udpShotPutWeightThrowResultsServer.on("message", function (ShotputWeightThrowmsg, ShotputWeightThrowinfo) {
tempShotputWeightThrowResults = ShotputWeightThrowmsg.toString();
finalShotputWeightThrowResults = finalShotputWeightThrowResults+tempShotputWeightThrowResults;
finalShotputWeightThrowResults = finalShotputWeightThrowResults.trim()
console.log(finalShotputWeightThrowResults);
//if (tempShotputWeightThrowResults == '~'){
console.log(finalShotputWeightThrowResults);
ShotputWeightThrowArray = finalShotputWeightThrowResults.split(';');
for (var a = 0; a < ShotputWeightThrowArray.length; a++) { =
ShotputWeightThrowArray[a]= ShotputWeightThrowArray[a].split(',');
}
var serv_io = io.listen(htmlServer, { log: false });
serv_io.sockets.on('connection', function(socket){
//send data to client
setInterval(function(){
jsonResults = JSON.stringify({
'runningobj': ShotputWeightThrowArray,
'shotputweightthrowobj': RunningArray,
'longtriplejumpobj': LongTripleJumpArray,
'highjumpobj': HighJumpArray,
'polevaultobj': PoleVaultArray
});
console.log(jsonResults);
socket.send(jsonResults);
}, 1000);
});
Here is an example of what is coming through the socket.
{"runningobj":["0.0",["UNOFFICIAL","Decat Men 110 Meter Hurdles","nwi","41","6","4","041-6-04","AUTO","4"],["","2","504","Klaus Ambrosch","Arizona","","","","","","","","","",""],["","4","693","Troy McDonough","Montana","","","","","","","","","",""],["","6","818","Pat Buckheit","Tennessee","","","","","","","","","",""],["","8","746","James Cook","Penn State","","","","","","","","","",""],",,,,,,,,,,,,,,",",,,,,,,,,,,,,,",",,,,,,,,,,,,,,",",,,,,,,,,,,,,,",",,,,,,,,,,,,,,",",,,,,,,,,,,,,,",",,,,,,,,,,,,,,",",,,,,,,,,,,,,,",",,,,,,,,,,,,,,",",,,,,,,,,,,,,,",["\u0003\u0004"]],"shotputweightthrowobj":[["\u0001R\u0002Unofficial","HammerThrowWomen","","19","1","1","019-1-01",""],["1","1","79","Crozier","Unattached","33.55","","110'01\""],["~"],["","","","","","","",""],["~"],["","","","","","","",""],["~"],["","","","","","","",""],["~"]],"longtriplejumpobj":[],"highjumpobj":[],"polevaultobj":[]}

Related

Net.Socket instances don't go away in NodeJS

I'm trying to recreate the functionality of a hardware serial server with Node and it's actually working, but I'm getting errors from socket instances that have been closed.
Here's a simplified version of the app to show what I'm doing...
var net = require('net');
var SerialPort = require('serialport');
var connectionCounter = 0;
var port = new SerialPort('/dev/ttyUSB0', function () {
var server = net.createServer();
server.on('connection',function(socket) {
connectionCounter++;
var connNumber = connectionCounter;
socket.on('error', function () {
console.log('socket ' + connNumber + ' errored');
});
socket.on('data', function(data) {
port.write(data);
});
port.on('data', function(data) {
socket.write(data);
});
});
server.listen(8887, '127.0.0.1');
}
});
So the first chunk of code that's sent into the 8887 port works fine, and it returns the data back out through the socket. The errors start on the second chunk. In the example, I'm keeping a count of the socket instances and outputting the socket instance number with the error. So as the program runs, the number of sockets instances keeps going up. The most recent instance will eventually handle the data, but I can't figure out what I need to delete to clean up all of the previous socket instances so they'll stop trying to process the incoming data.
I've tried socket.end() and socket.destroy(), but those don't seem to work . Do I need to go as far as deleting the server itself and recreating it?
If anyone ever finds this and cares about what was going wrong, I was setting an event listener on the serialport object every time a new net socket was created. So even though I was deleting the socket every time it was closed, the serialport listener was trying to send data to all of the old deleted sockets. So the solution was to removeListeners from the serialport object upon closing the net socket.
you can use array for storing sockets later on you can delete. this is sample code hope you got the idea
var net = require('net');
var SerialPort = require('serialport');
var connectionCounter = 0;
var mySockets = [];
var port = new SerialPort('/dev/ttyUSB0', function () {
var server = net.createServer();
server.on('connection',function(socket) {
mySockets.push(socket);
connectionCounter++;
var connNumber = connectionCounter;
socket.on('error', function () {
console.log('socket ' + connNumber + ' errored');
});
socket.on('data', function(data) {
port.write(data);
});
port.on('data', function(data) {
socket.write(data);
});
});
server.listen(8887, '127.0.0.1');
}
//get the sockets you want to delete
var s = mySockets.pop();
s = null;
});

Beaglebone Black revC

I am connecting BBB and a set of arduinos over the serial port (ttyO2).
I have an array to be sent from BBB to a set of arduinos.
I need to make the BBB sends a request and wait for a reply from one of the arduinos, but if no arduino replies within an interval, the BBB must send the following value in the array.
I have the connection and arduinos ready for their jobs.
The problem is that the BBB will listen on the port and complete the execution of the code at the same time. I need to make it listen for a specific time, if data received=> process it; else complete the following part of code (send the remaining part of the array). This job need to be in a loop.
I have been trying to use setTimeout, recursion, but with no success!
I am using the following code to listen and write on ttyO2:
` var b = require('bonescript');
//opening the serial port
var SerialPort = require("serialport").SerialPort
var serialPort = new SerialPort('/dev/ttyO2', {
baudrate: 115200
});
var i = 0;
serialPort.on("open", function () {
console.log('opened');
serialPort.on('data', function(data) {
console.log('data received: ' + data);
serialPort.write( i + "\n", function(){});
});
});
serialPort.on("data", function (data) {
console.log("here: "+data);
});
`
var b = require('bonescript');
//opening the serial port
var SerialPort = require("serialport").SerialPort;
var serialPort = new SerialPort('/dev/ttyO2', {
baudrate: 115200
});
var i = 0;
var waiting_interval = 5000;
var slaves = ["S1", "S2" , "S3", "S4", "S5"];
serialPort.on('open',function my(){
console.log("opened");
serialPort.on('data', function listenToSlaves(data){
console.log("returned: " + data);
});
writeToSlaves();
});
function writeToSlaves(){
// setInterval(serialPort.write(slaves[i], function(){ console.log("I
wrote to slave: " + i)}), 5000);
serialPort.write(slaves[i], function(){ });
console.log("I wrote to slave: " + i);
if(i<slaves.length - 1) i++;
else i=0;
setTimeout(writeToSlaves, waiting_interval);
}

NodeJs Convert 'net' socket to SSL/TLS based socket?

I have following nodejs code running on the server (chat engine). I want to convert this into a secure SSL/TLS based connection. How do i do that ?
In the client side (see below code), everytime i tried to convert this into SSL it gives me a error of "Cross origin request failed." i dont know why ?
NODE.JS Server Side Code
var cluster = require('cluster');
var net = require('net');
var fs = require('fs');
var config = require('./config.js');
var num_processes = 1;//require('os').cpus().length;
if (cluster.isMaster) {
// This stores our workers. We need to keep them to be able to reference
// them based on source IP address. It's also useful for auto-restart,
// for example.
var workers = [];
// Helper function for spawning worker at index 'i'.
var spawn = function (i) {
workers[i] = cluster.fork();
// Optional: Restart worker on exit
workers[i].on('exit', function (worker, code, signal) {
if (config.server.restart_instances_on_crash) {
spawn(i);
logging.log('debug', 'Node instances exited, respawning...');
}
});
};
// Spawn workers.
for (var i = 0; i < num_processes; i++) {
spawn(i);
}
// Helper function for getting a worker index based on IP address.
var worker_index = function (ip, len) {
var s = '';
for (var i = 0, _len = ip.length; i < _len; i++) {
if (ip[i] !== '.') {
s += ip[i];
}
}
return Number(s) % len;
};
/* wait 5 seconds to make sure all the instances are running and initialized */
setTimeout(function () {
// Create the outside facing server listening on our port.
var options = {
pauseOnConnect: true
};
var server = net.createServer(options, function (connection) {
// We received a connection and need to pass it to the appropriate
// worker. Get the worker for this connection's source IP and pass
// it the connection.
var str = connection.remoteAddress;
var ip = str.replace("::ffff:", '');
var worker = workers[worker_index(ip, num_processes)];
worker.send('sticky-session:connection', connection);
}).listen(config.server.listenport);
logging.log('debug', 'Server listening on ' + config.server.listenip + ':' + config.server.listenport + '...');
}, 5000);
process.on('uncaughtException', function (error) {
logging.log('error', 'uncaughtException');
logging.log('error',error.stack);
process.exit(1);
});
} else {
var express = require('express');
var sio = require('socket.io');
var sio_redis = require('socket.io-redis');
var dateandtime = require('./includes/dateandtime.js');
var stats = require('./includes/stats.js');
var helper = require('./includes/helper.js');
// Note we don't use a port here because the master listens on it for us.
var app = new express();
// Don't expose our internal server to the outside.
var server = app.listen(0, 'localhost'),
io = sio(server);
io.set('origins', '*:*');
}
In my Client side i have following code based socket.io JS module. (All these works fine without the SSL connection when using net module only)
Following is the client side javascript code to connect to the node server using socket.io functions.
var root_url = 'http://'+window.location.hostname;
var socket_io = 'http://example.com/js/chat/socket.io-1.3.5.js';
$(document).ready(function () {
$.getScript(socket_io, function () {
socket = io.connect(root_url + ':8440');
... etc
Can only hint you into checking the cors package for crossdomain requests but the deeper issue could be that not everything is running in SSL. (mixed http & https)

turning off a sockets stream

I have a sockets stream that is attached to the twitter api and I need to find a way to toggle it on and off. I was attempting to use an array as a sort of counter and an if statement to break the stream when it filled to 10 bits of location data.
var startArray = [];
io.on('connection', function(socket) {
if(startArray.length < 10){
console.log('a user connected');
// socket.on('twitter-stream', function(input) {
client.stream('statuses/filter', {locations:'-180,-90,180,90'}, function(s) {
stream = s;
stream.on('data', function(data) {
// console.log(data);
// Does the JSON result have coordinates
// console.log(data.text)
if (data.coordinates){
if (data.coordinates !== null ){
//If so then build up some nice json and send out to web sockets
var outputPoint = {"lat": data.coordinates.coordinates[0],"lng": data.coordinates.coordinates[1]};
startArray.push(outputPoint);
io.emit("twitter-stream", outputPoint);
console.log(outputPoint);
console.log(startArray.length);
// console.log(data.text);
// console.log(data.text);
//Send out to web sockets channel.
io.emit('twitter-stream', outputPoint);
}
}
});
// }); // end client stream
}) // end socket 'activate'
};//end of if statement
});//end of sockets`
^^
This section is in my server.js
This section is my sockets.js It was supposed to contain a button that was able to toggle the state of my stream, but that did not seem to work, whether it was turning the stream on or off.
vv
var socket = io();
var locationsArray = [];
$(document).on('click', '#start-stream', function(){
console.log('start-stream');
socket.on('twitter-stream', function(tweet) {
//only selects tweets with coordinates
console.log(tweet);
var coolShit = tweet;
locationsArray.push(coolShit);
});
})

Creating a map of ids to sockets and vice versa in Node.js

I'm trying to manage a bunch of socket connections. My app is basically an http server that receives posts and passes these along to a socket. When clients open a socket connection, they send a connect message with an id:
{"m":"connect","id":"1"}
The app then saves this id and socket in the id2socket and socket2id maps. On disconnect, the socket/id pair is deleted from the maps.
A post will also contain an id, which indicates the post data should be sent to the socket with that id.
That's great, and this works fine for a single open socket. However, when I have more than one socket open, and then I close a socket, that disconnect wipes everything from the map. I think my understanding of sockets in node is incomplete- is there only a single socket object that is used in the callback? Is there a better way to manage my open socket connections and ids?
start server:
>>node server.js
TCP server listening on 127.0.0.1:5280
HTTP server listening on 127.0.0.1:9002
telnet in:
>>telnet localhost 5280
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
{"m":"connect","id":"123"}
{"m":"connect","id":"123","success":"true"}
server after connection:
>>Connection from 127.0.0.1:57572
received data: {"m":"connect","id":"123"}
id: 1
m: connect
associating uid 1 with socket [object Object]
do a post:
python post.py {"foo":"bar"}
So this works fine for several open sockets (as long as 1 device is id 123, server has this hardwired for now). However, as soon as you close one connection all the socket connections are removed from the map.
Here's my code:
python script to do post:
import sys
import json
import httplib, urllib, urllib2
values = json.loads('{"foo":"bar"}')
headers = {"Content-type": "application/json"}
conn = httplib.HTTPConnection('127.0.0.1', 9002)
headers = {"Content-type": "application/json"}
conn.request("POST", "", json.dumps(values), headers)
response = conn.getresponse()
print "response.status: "+response.status
print "response.reason: "+response.reason
print "response.read: "+response.read()
conn.close()
node server (http and tcp), hardwired to send data to device '123' on post:
var net = require('net'); // tcp-server
var http = require("http"); // http-server
var qs = require('querystring'); // http-post
// Map of sockets to devices
var id2socket = new Object;
var socket2id = new Object;
// Setup a tcp server
var server_plug = net.createServer(function(socket) {
// Event handlers
socket.addListener("connect", function(conn) {
console.log("Connection from " + socket.remoteAddress + ":" + socket.remotePort );
});
socket.addListener("data", function(data) {
console.log("received data: " + data);
try {
request = JSON.parse(data);
response = request;
if(request.m !== undefined && request['id'] !== undefined){ // hack on 'id', id is js obj property
console.log("id: "+request['id']);
console.log("m: "+request.m);
if(request.m == 'connect'){
console.log("associating uid " + request['id'] + " with socket " + socket);
id2socket[request['id']] = socket;
socket2id[socket] = request['id'];
response.success = 'true';
} else {
response.success = 'true';
}
}
socket.write(JSON.stringify(response));
} catch (SyntaxError) {
console.log('Invalid JSON:' + data);
socket.write('{"success":"false","response":"invalid JSON"}');
}
});
socket.on('end', function() {
id = socket2id[socket]
console.log("socket disconnect by id " + id);
// wipe out the stored info
console.log("removing from map socket:"+socket+" id:"+id);
delete id2socket[id];
delete socket2id[socket];
});
socket.on('timeout', function() {
console.log('socket timeout');
});
});
// Setup http server
var server_http = http.createServer(
// Function to handle http:post requests, need two parts to it
// http://jnjnjn.com/113/node-js-for-noobs-grabbing-post-content/
function onRequest(request, response) {
request.setEncoding("utf8");
request.addListener("data", function(chunk) {
request.content += chunk;
});
request.addListener("end", function() {
console.log("post received!");
//console.log("Request received: "+request.content);
if (request.method == 'POST') {
//var json = qs.parse(request.content);
//console.log("Post: "+json);
// HACK TO TEST STUFF:
// send a message to one of the open sockets
try {
var socket = id2socket['123']; //hardwired
socket.write('{"m":"post"}');
} catch (Error) {
console.log("Cannot find socket with id "+'123');
}
}
});
}
);
// Fire up the servers
var HOST = '127.0.0.1';
var PORT = 5280;
var PORT2 = 9002;
server_plug.listen(PORT, HOST);
console.log("TCP server listening on "+HOST+":"+PORT);
server_http.listen(PORT2);
console.log("HTTP server listening on "+HOST+":"+PORT2);
Objects only take strings as keys for their properties. As your log shows, a socket object is converted into the string "[object Object]". As a result, socket #2 overwrites the id from socket #1 in the object, because all sockets are converted into the same string key. So, there is only one property in the object at all times, because all sockets come down to the same key. When you try to remove the id for socket #2, the single property is deleted and the object is empty.
You seem to want a custom property for each separate socket when used as a key. You can use WeakMaps for this. WeakMaps do allow objects as keys (as opposed to string-only keys), but as they're relatively new they may contain bugs at the moment.
(Note that the id2socket map can just be a plain object, because numbers are converted into strings just fine, and each number has its own, distinct string representation*.)
Using WeakMaps is as follows:
var socket2id = new WeakMap; // as if you were doing: var socket2id = {};
socket2id.set(socket, id); // as if you were doing: socket2id[socket] = id;
socket2id.get(socket); // as if you were doing: socket2id[socket];
socket2id.delete(socket); // as if you were doing: delete socket2id[socket];
Make sure to run with node --harmony (>= 0.7) or node --harmony_weakmaps (<= 0.6).
* 0 and -0 are exceptions, but you shouldn't be using -0 anyway because 0 === -0, so it's difficult to differ between them.

Categories

Resources