How to bind property to socket object using deployd? - node.js

I don't even know if that question makes sense. I don't have a lot of experience with socket.io or deployd. You'll probably understand what I'm trying to do from my code. It's similar to this. Here is my server code.
var deployd = require('deployd');
var options = {
//options go here
};
var dpd = deployd(options);
dpd.listen();
dpd.on('getLobby', function (lobby) {
dpd.lobby = lobby; //trying to bind variable to socket
console.log('get Lobby');
});
dpd.on('disconnect', function() {
console.log("disconnected");
});
dpd.on('connection', function (socket) {
console.log('connection');
});
and on my client side I have this
dpd.socket.emit('getLobby', lobby, function (data) {
console.log("emitted");
console.log(data);
});
The server works. My app works. Everything runs fine except for this code. I get no errors and no console logs. None of this code seems to work at all. It doesn't seem to emit and it doesn't seem to catch an emission if there even is one. I have tried lots of different ways of writing this.

Related

Node Websockets Broadcast not working

Currently having an issue with "Broadcast" not seeming to function properly with a super simple websocket setup I started in Node. This is my first time working with websockets so I may be missing something pretty apparent, but after looking online for a while I wasn't able to find a resolution.
Basically I am just trying to have the ability to push some json out to all currently connected Clients.
I can confirm that that socket is working because I am able to see the static connection string on 'ws.send' in the 'connection' block when I connect at ws://localhost:3000, as well as seeing mulitple clients logged out from the broadcast method if I connect with multiple clients.
Any help as to what I may be missing would be greatly appreciated,
var WebSocketServer = require('uws').Server;
var wss = new WebSocketServer({ port: 3000 }); // ws://localhost:3000
// Static test var
var test_message = {
'test': 'Response',
'test2': 'Response2'
};
// Broadcast to all.
wss.broadcast = function broadcast(data) {
wss.clients.forEach(function each(client) {
console.log('IT IS GETTING INSIDE CLIENTS');
console.log(client);
// The data is coming in correctly
console.log(data);
client.send(data);
});
};
wss.on('connection', function(ws) {
ws.on('message', function(message) {
wss.broadcast(test_message);
console.log('Received: ' + message);
});
// TODO This is static just to check that the connection is properly working
ws.send('You successfully connected to the websocket.');
});
I tested your code with Smart Websocket Client. Your code is fine. If you broadcast data having string only, then you can see the reply in UI, but for javascript object, the client doesn't display although you can see response as Binary Frames (opcode = 2) in Chrome Developer Tools.
The reason behind this behavior is that the ws.send() method support normal strings, typed arrays or blobs, but sending typed arrays and blobs will result in the frame(s) received by the client as binary frames (opcode = 2).
You can try JSON.stringify the object,
wss.on('connection', function(ws) {
ws.on('message', function(message) {
wss.broadcast(JSON.stringify(test_message));
console.log('Received: ' + message);
});
ws.send('You successfully connected to the websocket.');
});

Use socket.io-client with Express and nodejs to send query to java server

I have a web app built upon Express. The nodejs backend is using a java server to perform some heavy operations. The dialogue between Express and the java server is done using socketio. The nodejs server is the client and uses socket.io-client to send queries to the java server. The javaserver is based upon netty-socketio.
Here is what I am doing in my nodejs app:
var io = require('socket.io-client')
var socket = io.connect('http://localhost:8080');
socket.on('connect', function () {
console.log('0 Connected!');
socket.emit('myEvent', ['0' ,'here is the query'], function (data) {
console.log('\tSending query ... waiting for ACK0');
console.log(data);
});
socket.on('serverResponse', function (data) {
console.log('\tserverResponse event triggered, data:');
console.log(data);
});
});
When calling this script outside my web app everything is working like a charm, but when I call this code from express my client fails to connect (I don't reach the '0 Connected!' line). There are no error messages.
The weird part is that if I am first running my web app, throwing a query, and then start my java server, the client connects to the java server and everything is working (for that query only). Any clues on how to fix that ?
EDIT 1
Here is a schema of what I am trying to achieve:
client javascript backend java server
via browser <---> node/Express/socketio-client <---> netty-socketio
#client's machine | #my server | #my server (the same)
| |
myDNS:80 localhost:8080
More precisions on the java server. Here is the squeleton:
public class App {
public static void main(String[] args) throws InterruptedException, UnsupportedEncodingException {
Configuration config = new Configuration();
config.setHostname("localhost");
config.setPort(8080);
final SocketIOServer server = new SocketIOServer(config);
server.addEventListener("myEvent", String[].class, new DataListener<String[]>() {
#Override
public void onData(final SocketIOClient client, String[] data, final AckRequest ackRequest) {
//Id of the client
String id = data[0];
//Acknowledge the request:
ackRequest.sendAckData("ACK_"+id);
//doing some calculations ...
// ... ... ...
// ... ... ...
client.sendEvent("serverResponse", new VoidAckCallback(){
#Override
protected void onSuccess() {}
}, "I am the answer from the server");
}
});
server.start();
System.out.println("[JAVA SERVER INFO] Java server started.");
Thread.sleep(60000*3);//Integer.MAX_VALUE);
server.stop();
System.out.println("[JAVA SERVER INFO] Java server stopped.");
}
}
My web app nodejs backend and my java server are running on the same machine, the communication with socket.io is done via localhost:8080. Once again, the weird thing is that the client's script is working when used outside the express framework, this let me think it might be a compatibility problem between socket.io-client and Express.
EDIT 2
I modified my socket.io-client code to see with more details what is happening, I added:
socket.on('connect_error', function(err){
console.log(err);
});
socket.on('connect_timeout', function(){
console.log("connect_timeout");
});
socket.on('reconnect_attempt', function(){
console.log("reconnect_attempt");
});
When I run the client with the java server switched off, I get a 'connect_error' event. When the java server is on I get no message at all. It seems the connection is neither failing nor successful, nothing happen ... Any idea on how to debug this better ?
EDIT 3
Here is the code I am using to handle a request from the browser:
index.js:
var express = require('express');
var router = express.Router();
var controller = require('../controllers/myController.js');
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
module.exports = router;
router.post('/api/getProcessedData', function(req, res, next){
var text = req.body.text;
controller.get_processed_data(text, res);
});
myController.js:
var socket = require('socket.io-client')('http://localhost:8080');
module.exports.get_processed_data = function(text, res) {
var timestamp = new Date().getTime();
console.log('starting client');
socket.on('connect', function () {
console.log("client connected.");
socket.emit('myEvent', [timestamp ,text], function (data) {
console.log('\tSending query ... waiting for ACK');
console.log(data);
});
socket.on('serverResponse', function (data) {
console.log('\tserverResponse' event trigged, data:');
res.send(data);
});
});
socket.on('connect_error', function(err){
console.log(err);
});
socket.on('connect_timeout', function(){
console.log("connect_timeout");
});
socket.on('reconnect_attempt', function(){
console.log("reconnect_attempt");
});
socket.on('reconnecting', function(){
console.log("reconnecting");
});
}
The structure of your controller is a bit messed up. Here are some things that are wrong:
You connect to the Java server when the module is loaded, but you don't assign a connect event handler until the route gets hit. This means you will normally miss the connect event except when the server isn't yet running. So, this entirely explains what you observe. If the java server is already up when you start your Express server, you miss the connect event so you never execute any of the logic in your get_processed_data() function.
You install a new connect handler every time the route is hit which means you will get multiple event handlers assigned, though because of the first issue, none of them will likely get hit.
If you want the socket.io connection to be continually connected, this would be one way to rewrite the controller:
var socket = require('socket.io-client')('http://localhost:8080');
socket.on('connect', function () {
console.log("client connected.");
});
socket.on('connect_error', function(err){
console.log(err);
});
socket.on('connect_timeout', function(){
console.log("connect_timeout");
});
socket.on('reconnect_attempt', function(){
console.log("reconnect_attempt");
});
socket.on('reconnecting', function(){
console.log("reconnecting");
});
var transactionCntr = 0;
module.exports.get_processed_data = function(text, res) {
var timestamp = new Date().getTime();
var transactionId = transactionCntr++;
console.log('sending data to client');
function onResponse(data) {
// for concurrency reasons, make sure this is the right
// response. The server must return the same
// transactionId that it was sent
if (data.transactionId === transactionId) {
console.log('\tserverResponse' event trigged, data:');
res.send(data);
socket.off('serverResponse', onResponse);
}
}
socket.on('serverResponse', onResponse);
// send data and transactionId
socket.emit('myEvent', [timestamp ,text, transactionId], function (data) {
console.log('\tSending query ... waiting for ACK');
console.log(data);
});
}
Your current structure has an issue in that it does not appear to have a way to determine which response goes with which request and can have concurrency issues. It would be simpler to just use a separate http request each time because then the response would be uniquely paired with the appropriate request.
With your socket.io connection, you could use some sort of ID in your request/response so you can tell which response belongs to which request. I've shown how that would work in the express server. From your Java server, you would have to echo the transactionId back in the response to the Express server so it can track which response goes with which request.
As your code was, if multiple requests for the '/api/getProcessedData' route are in play at the same time, the responses from the different requests could easily get mixed up. This is an architectural problem of the way you're doing things.
I'm no Java expert, but it looks to me like this line:
Thread.sleep(60000*3);
will sleep your thread for 180,000 milliseconds (3 minutes) and then right after that your code calls server.stop(). So, your Java server shuts itself down after 3 minutes.
So, thus you could only connect to your Java server within the first 3 minutes after you started it.
The logical question here is why are you stopping your server at all?

Request not ending in node.js (used to work)

I have this piece of code:
var app = require('http').createServer(function(req, res){
console.log(req);
req.addListener('end', function () {
fileServer.serve(req, res);
});
});
var statics = require('node-static');
var fileServer = new statics.Server('./');
app.listen(1344, '127.0.0.1');
app.on('error', function(err){
console.log(err);
})
It was working just fine, till I made a couple of changes, node gives an error, and when I went back, that error wasn't there anymore, but instead of work like it was working before the end event is not being fired. So, anything inside req.addListener('end', function (){});is not called.
And even if I run another node.js that uses the same event, is not being fired either. So is like if the end event of the request is broken. But how can that be possible?
Is not the first time it happens. Last time I ended up re-installing node (after try lots of different things). I would prefer to find a solution, so I can understand the problem!
NOTE: The original code include socket.io and other kind of connections, but I've just pasted the piece of code were the app is stuck on.
It could also be useful to know how to debug the problem!
#InspiredJW should get credit for pointing this out, since I had forgotten about it, but undoubtedly your problem is because of the changes in the readable streams. In order for the end event to get called you either have to attach a listener to the data event, or you have to call stream.resume().
require('http').createServer(function(req, res){
req.addListener('end', function () {
// won't ever get called in node v0.10.3
});
});
require('http').createServer(function(req, res){
req.addListener('end', function () {
// will get called in node v0.10.3 because we called req.resume()
});
req.resume();
});
require('http').createServer(function(req, res){
req.on('data', function (chunk) { });
req.addListener('end', function () {
// also will get called because we attached a data event listener
});
});
http://nodejs.org/api/stream.html#stream_compatibility

Socket.io : How do I handle all incoming messages on the server?

I want to be able to handle all messages that are coming in from clients in a single handler.
Example client code:
var socket = io.connect('http://localhost');
socket.emit('news', { hello: 'test' });
socket.emit('chat', { hello: 'test' });
Example server code:
io.sockets.on('connection', function (socket) {
socket.on('message', function (data) {
console.log(data);
}); });
I'd like to be able to log every message even if its sent on news, chat or whatever other name using emit. Is this possible?
Note: The above server code does not work. There is nothing currently logged. I am just wondering if there is a single event which could be handled for all messages for every emit name.
That is possible by overriding socket.$emit function
//Original func
var x = socket.$emit;
socket.$emit = function(){
var event = arguments[0];
var feed = arguments[1];
//Log
console.log(event + ":" + feed);
//To pass listener
x.apply(this, Array.prototype.slice.call(arguments));
};
It's even easier on Socket.Io >3 using the socket.onAny(listener):
this.socket.onAny(m => {
..
});
This is supported out of the box now as of Socket-io 2.0.4, you simply need to register a middle ware (source from socketio-wildcard):
As of Socket.io v2.0.4 (commit), you can use a socket middleware to
catch every incoming Packet, which satisfies most of
socketio-wildcard's use cases.
io.on('connection', (socket) => {
socket.use((packet, next) => {
// Handler
next();
});
});
This is an open issue with Socket.IO.
At this time, if you really need it, you will probably have to fork Socket.IO. See 3rd-Edens comment for how to do it.

Waiting for an event in Node.js

I have been playing with Node.js for some time.
I have the following piece of script in my server:
socket.on('auth', function(uid, key) {
client.hgetall(uid, function (err, data) {
console.log(data);
if(key != data['key']) {
socket.disconnect();
}
this.user = data;
});
});
socket.on('loginGame', function(gameId) {
checkAuth();
console.log(user);
if(!games[gameId]) {
games[gameId] = {};
}
games[gameId][uid] = uid;
});
In my client;
socket.on('connect', function(){
socket.emit('auth', 1, 1);
socket.emit('loginGame', 1);
});
When I run this code, loginGame function finishes before auth function as I am doing I/O (using redis). I know this a feature of node.js, but I think I am missing something. How can I overcome this issue as auth function needs to finish before running any function. (I have a couple of more functions which need to run in serial)
I have found a node.js module: https://github.com/creationix/step . However, is this the only option? I think this is something most node.js developer might need. I am not that good at JS either.
What is the best and most elegant way of solving this issue?
Thanks,
Have the server send back an acknowledgement when auth is successful, and send loginGame in the handler for that message.

Resources