multiple browser instances with websocket capabilities in node? - javascript

Let's say I am building a social app. I want to log into multiple accounts (one per browser instance) without an user interface (all via node), and by calling all respective endpoints to log in and start chatting.
The important part is to test when an user closed the tab or logs out or leaves the group and therefore the websocket's connection closes.

If I understand you correctly.
You would like to make a server-side event happen whenever a client connects or disconnects, without any html,css.... or any other user interface.
You can do it like this in node :
For connection you use :
Server.on("connection,function(ws){some stuff...})
The function that is called on connection will get the websocket that connected as parameter by default. I just use a lambda function here you can also call one that will then get the websocket as parameter.
For disconnection you put a function in the Server.on function to monitor when the client disconnected. Like this :
Server.on("connection,function(ws){
ws.onclose = function (ws) {
some stuff...
}
})
You can again replace the lambda function by another one.
Server is in my case equal to this :
const wsserver = require("ws").Server
const server = new wsserver({ port: someport })
But it can vary.
All you need to do apart from that is connect the client.
I do it like this but it can vary as well.
const ws = new WebSocket("ws://localhost:someport");
I hope this is helpful.

Related

How to create sockets that particular to user and disposable on Socket.Io

I write a Node.Js app and I use Socket.Io as the data transfer system, so requests should be particular to per user. How can I make this?
My actual code;
node:
io.on('connection', (socket) => {
socket.on('loginP', data => {
console.log(data);
})
})
js:
var socket = io('',{forceNew : false});
$("#loginbutton").click(function() {
var sessionInfo = {
name : $("#login input[name='username']").val(),
pass : $("#login input[name='pass']").val()
}
socket.emit("loginP", sessionInfo)
})
It returns one more data for per request and this is a problem for me. Can I make this on Socket.Io or should I use another module, and If I should, which module?
If I understand your question correctly (It's possible I don't), you want to have just one connection from each user's browser to your nodejs program.
On the nodejs side, your io.on('connection'...) event fires with each new incoming user connection, and gives you the socket for that specific connection. So, keep track of your sockets; you'll have one socket per user.
On the browser side, you should build your code to ensure it only calls
var socket = io(path, ...);
once for each path (your path is ''). TheforceNew option is for situations where you have multiple paths from one program.

Browser connecting with multiple sockets using JS socket.io

I'm using node.js with a React front end. I'm building a GPS based MMO type of game. I recently decided to drop most HTTP requests and go with sockets, so I can emit data whenever I want and the front end only has to worry about what to do with it when it receives it.
I've built sites with sockets before, but never ran into this issue.
Basically, every time my browser opens a socket connection with node, it opens 2-3 connections at once(?). When it disconnects, I get the console.log stating that 3 socket connectionss have been closed. It'll look like this:
User disconnected
User disconnected
A user has connected to the system with id: nUMbkgX6gleq-JZQAAAD
A user has connected to the system with id: CzFtR2K5NJ1SoiHLAAAE
A user has connected to the system with id: tgGYhpXuOONmL0rMAAAF
For now, it wouldn't be an issue, however I'm only getting the FIRST 'inventory' emit to work. Later when I call the function to emit inventory again, the browser doesn't seem to get it. But the console logs in the node function will trigger correctly.
I have a feeling that this has something to do with multiple sockets opening.
Here is the React Event:
this.socket.on("inventory", charData => {
console.log('heres the data', charData)
props.setCharStats(charData[0])
})
Here's the node emitter:
const getCharInventory = (charId, userId) => {
dbInstance
.getCharInventory(charId)
.then(response => {
console.log( // this console.log happens just fine
"emmited inventory, userId is: ", userId, " with this response: ", response)
socket.emit("inventory", response)
})
.catch(err => console.error(err))
}
I'm such a dork. I was starting multiple connections within multiple connections.
In more than one component, I had this...
this.socket = socketIOClient(`${process.env.REACT_APP_proxy}`)
Sooo..... yeah. Just an FYI to others, it's better to connect in 1 file and import it into others.

How to use the correct protocol for receiving active mq web socket stomp from java based program

I have a JavaScript based active mq listener, who is using stomp and web sockets.I was able to send test messages to active mq and receive them.
What I really want is it needs to be sent from a Java based code.
Is it Ok to have the JavaScript listening on web sockets/stomp and
the java code be using tcp ?
If it is OK, should all of the ports be the same?
I am having issues receiving data in JavaScript. However I am seeing the topic being enquued in the active mq.thanks
function subscribeEndpoint(endpoint){
var client = Stomp.client("ws://localhost:61614/stomp", "v11.stomp");
var headers = { id:'JUST.FCX', ack: 'client'};
client.connect("admin", "admin", function () {
client.subscribe(endpoint,
function (message) {
alert(message);
}, headers);
});
}
Java:
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616/stomp");
// Create a Connection
Connection connection = connectionFactory.createConnection();
connection.start();
// Create a Session
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// Create the destination (Topic)
Destination destination = session.createTopic("vrwrThreat");
// Create a MessageProducer from the Session to the Topic or Queue
MessageProducer producer = session.createProducer(destination);
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
// Create a messages
TextMessage message = session.createTextMessage(text);
producer.send(message);
// Clean up
session.close();
connection.close();
Clients can communicate with each other across protocols and transport mechanisms without issue. A STOMP client on WebSocket or any other port (TCP, SSL, etc) can send to a Topic and an AMQP, MQTT or OpenWire client can receive the message so long as the protocol supports the content of the message, same goes for the reverse case of AMQP, MQTT or OpenWire sending and STOMP receiving.
The case you've mentioned is pretty standard. The code you've posted appears to be using the OpenWire client to send to a Topic "vrwrThreat". The URI used in the connection factory is slightly off in that you added the '/stomp' which is meaningless. Since you are sending to a Topic you need to ensure that the client that is to receive the message is active at the time of transmission otherwise the message will be dropped. Also you need to ensure that both are operating on the same Topic which is unclear from your code snippets.

running a mysql query using mysql-npm on AWS

Hi guys I have a problem that i don't really have idea how to solve. it's also a bit strange :/
Basically I have created this Lambda function to connect to a mysql DB using the node package 'mysql'.
If i run the function from command line on my pc using the command 'sls function run function1' and make different queries everything is fine.
But when I call the function from a web browser using the link, I have to refresh the page 2 times to get the right result because at the first refresh the server respond with the old result.
I have noticed that from the command line I always have different thredID while from webbrowser is always the same.
Also I don't close the connection in the lambda function code because everything is fine if i run the function from command line but from browser I can only make 2 queries and then I get a message that say that I cannot use a closed connection.
So it seems like Lambda store the old query result when I call it from web browser.
Obviously I'm making same stupid mistake but I don't know how to solve it.
Does anyone have an idea?
Thanks :)
'use strict';
//npm packages
var mysql=require('mysql');
var deasync = require('deasync');
//variables
var goNext=false; //use to synchronize deasync
var error=false; //it becomes TRUE if an error occured during the connection to the DB
var dataColumnTable; //the data thet you extract from the query to the DB
var errorMessage;
//----------------------------------------------------------------------------------------------------------------
//always same credentials
var connection = mysql.createConnection({
host : 'hostAddress',
user : 'Puser',
password : 'password',
port : '3306',
database : 'database1',
});
//----------------------------------------------------------------------------------------------------------------
module.exports.handler = function(event, context) {
var Email=event.email;
connection.query('SELECT City, Address FROM Person WHERE E_Mail=?', Email, function(err, rows) {
if(err){
console.log("Cannot connect to DB");
console.log(err);
error=true;
errorMessage=err;
}
else{
console.log("data from column acquired!");
dataColumnTable=rows;
}
//connection.end(function(err) {
// connection.destroy();
//});
//console.log("Connection closed!");
goNext=true;
});
require('deasync').loopWhile(function(){return goNext!=true;});
//----------------------------------------------------------------------------------------------------------------
if(error==true)
return callback('Error '+ errorMessage);
else
return callback(null,dataColumnTable); //return a JsonFile
//fine headler
};
Disclaimer: I'm not very familiar with AWS and/or AWS Lambda.
http://docs.aws.amazon.com/lambda/latest/dg/programming-model-v2.html states (emphasis mine):
Your Lambda function code must be written in a stateless style, and have no affinity with the underlying compute infrastructure. Your code should expect local file system access, child processes, and similar artifacts to be limited to the lifetime of the request. Persistent state should be stored in Amazon S3, Amazon DynamoDB, or another cloud storage service. Requiring functions to be stateless enables AWS Lambda to launch as many copies of a function as needed to scale to the incoming rate of events and requests. These functions may not always run on the same compute instance from request to request, and a given instance of your Lambda function may be used more than once by AWS Lambda.
Opening a connection and storing it in a variable outside your handler function is state. The connection will likely be closed between requests or even before your first request. Your lambda function may be reused (hence identical thread ids).
My assumption would be (and an attempt to solve this problem), that you need to create the connection on every request (i.e., inside your handler) and may not expect any value be as initialized or as on last request. (except for constants probably).

Emit an event with node.js socket client to sails.js (0.11.x) [duplicate]

This question already has an answer here:
Emitting a message in sails v0.11 (client-side)
(1 answer)
Closed 6 years ago.
The server: sails.js (0.11.x) is the server
The client: A node.js script with sails.io#0.11.5 and socket.io-client#1.3.5
Big picture: I have, or will have, a farm of node.js scripts that connect to the sails.js server and will perform various tasks.
Immediate Goal: I want to emit an event during a socket connection from client->server such as:
socket.emit('got_job', job.id);
Why? If this is possible I can create various event handlers on the server side in one controller (or controller + service) and keep my code clean while managing a set of stateful transactions between client/server endpoints for supporting this script farm.
The documentation: This is how one goes about using socket.io-client for sails.js this per sails docs: https://github.com/balderdashy/sails.io.js?files=1#for-nodejs
I haven't much code to share other than what's in that link, but I'll paste it here just in case:
var socketIOClient = require('socket.io-client');
var sailsIOClient = require('sails.io.js');
// Instantiate the socket client (`io`)
// (for now, you must explicitly pass in the socket.io client when using this library from Node.js)
var io = sailsIOClient(socketIOClient);
// Set some options:
// (you have to specify the host and port of the Sails backend when using this library from Node.js)
io.sails.url = 'http://localhost:1337';
// ...
// Send a GET request to `http://localhost:1337/hello`:
io.socket.get('/hello', function serverResponded (body, JWR) {
// body === JWR.body
console.log('Sails responded with: ', body);
console.log('with headers: ', JWR.headers);
console.log('and with status code: ', JWR.statusCode);
// When you are finished with `io.socket`, or any other sockets you connect manually,
// you should make sure and disconnect them, e.g.:
io.socket.disconnect();
// (note that there is no callback argument to the `.disconnect` method)
});
What I have looked into: I've drilled into various levels of these objects and I can't seem to find anything exposed to use. And simply trying io.socket.emit() as it doesn't exist. But io.socket.get() and io.socket.post(), etc work fine.
console.log(socketIOClient);
console.log(sailsIOClient);
console.log(io);
console.log(io.socket._raw);
console.log(io.sails);
Thanks, and I'll try to update this as needed for clarification.
UPDATE:
Misc Server Info.:
I'm using nginx on port 443, with SSL termination, pointing to 4 (and
soon more) sails.js instances on separate ports (3000-3003).
I'm also using Redis for sessions and sockets.
You're close:
Your io.socket.get call is kind of like a rest api call. You'd need a sails controller bound to a get request on the url '/hello',
//client
io.socket.get('/hello', function serverResponded (body, JWR) {
//this is the response from the server, not a socket event handler
console.dir(body);//{message:"hello"}
});
in
config/routes.js:
{
'get /hello':'MyController.hello'
}
//controllers/MyController
{
hello:function(req,res){
res.json({message:"hello"});
}
}
The method you're looking for is, io.socket.on('eventName');
Here's an example:
//client
io.socket.get('/hello', function serverResponded (body, JWR) {
//all we're doing now is subscribing to a room
console.dir(body);
});
io.socket.on('anevent',function(message){
console.dir(message);
});
in
config/routes.js:
{
'get /hello':'MyController.hello'
}
//controllers/MyController
{
hello:function(req,res){
sails.sockets.join(req.socket,'myroom');
res.json({message:'youve subscribed to a room'});
}
}
What we've effectively done is, setup our socket to be part of a "room", which is basically an event namespace. Then, some other controller only has to do this:
sails.sockets.broadcast('myroom','anevent',{message:'socket event!'});
After this call is made, you would receive the message in the callback of io.socket.on('anevent').

Categories