turning off a sockets stream - javascript

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);
});
})

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;
});

SignalR javascript client not picking up event from hub

I have a method on the hub however I am not getting any messages from this. I get the connection ID's from my user to connectionid mapping dictionary and loop through these connectionid's and then invoke a method on the client side called deviceDiscovered I can also confirm that the browser does connect to the hub
Here is my hub method
public async Task DetectDevice(dynamic message)
{
//We will be searching via the userid
var connectionId = Context.ConnectionId;
//now we get the connectionID from the table.
var connectionObj = ConnectionTable[connectionId];
//we now check whether this is a pathfinder or browser client
if (connectionObj.clientType == "pathfinder")
{
/*The pathfinder initiated the request and so this means the message should be forwarded to the browser client
that requested this resource*/
//Grab the data out of the dictionary.
PathfinderDetection deviceDiscoveredNotification = JsonConvert.DeserializeObject<PathfinderDetection>(message);
var userId = deviceDiscoveredNotification.userId;
var sysInfo = deviceDiscoveredNotification.sysInfo;
var found = deviceDiscoveredNotification.data;
if (found == "FOUND")
{
var deviceId = deviceDiscoveredNotification.deviceID;
var connections = ConnectionTable.Where(val => val.Value.id == connectionObj.id).Select(key => key.Key).ToList();
foreach (string connection in connections)
{
Clients.Client(connection).deviceDiscovered(deviceId);
}
}
else
{
//call a method on client side.
Clients.Group(userId.ToString()).noDevice("NOTFOUND");
}
I can see that the deviceID variable is populated and that the connection exists, however not getting anything back from the hub when looking at the client
here is my client side code:
<script>
$(document).ready(function(){
var connection = $.hubConnection("http://localhost:59016");
var contosoChatHubProxy = connection.createHubProxy('metrics');
contosoChatHubProxy.on('taskAdded', function(data){
console.log(data);
});
contosoChatHubProxy.on('deviceDiscovered', function(data) {
console.log(data);
});
contosoChatHubProxy.on('taskUpdate', function(data){
console.log(data);
});
contosoChatHubProxy.on('noDevice', function(found) {
console.log(found);
});
});
</script>

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

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":[]}

How do I close a sockjs connection on the server side?

So, every time I refresh the page, it seems like sockjs is creating a new connection.
I am saving every message to my mongodb on every channel.onmessage, so if I refresh my page 7 times and send a message, I would save 7 messages of the same content into my mongodb.
This is very problematic because when I retrieve those messages when I go into the chat room, to see the log, I would see bunch of duplicate messages.
I want to keep track of all connections that are 'active', and if a user tries to make another connections, I want to be able to force close on the old one from the server side, so there is only 1 connection listening to each message at a time
How do I do this ?
var connections = {};
//creating the sockjs server
var chat = sockjs.createServer();
//installing handlers for sockjs server instance, with the same url as client
chat.installHandlers(server, {prefix:'/chat/private'});
var multiplexer = new multiplexServer.MultiplexServer(chat);
var configChannel = function (channelId, userId, userName){
var channel = multiplexer.registerChannel(channelId);
channel.on('connection', function (conn) {
// console.log('connection');
console.log(connections);
connections[channelId] = connections[channelId] || {};
if (connections[channelId][userId]) {
//want to close the extra connection
} else {
connections[channelId][userId] = conn;
}
// }
// if (channels[channelId][userId]) {
// conn = channels[channelId][userId];
// } else {
// channels[channelId][userId] = conn;
// }
// console.log('accessing channel! ', channels[channelId]);
conn.on('new user', function (data, message) {
console.log('new user! ', data, message);
});
// var number = connections.length;
conn.on('data', function(message) {
var messageObj = JSON.parse(message);
handler.saveMessage(messageObj.channelId, messageObj.user, messageObj.message);
console.log('received the message, ', messageObj.message);
conn.write(JSON.stringify({channelId: messageObj.channelId, user: messageObj.user, message: messageObj.message }));
});
conn.on('close', function() {
conn.write(userName + ' has disconnected');
});
});
return channel;
};
Simply use .close:
if (connections[channelId][userId]) {
// want to close the extra connection
connections[channelId][userId].close();
} else {
connections[channelId][userId] = conn;
}

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