How can I establish one connection between a user and the WebSocket? - javascript

I have websocket running on a node/Express server.
I need to send json string back and fourth between a websocket and a client.
However, if a user opens more than one browser's tab, I like for the websocket server to know that this is the same user that is already connected.
Here is the logic execution order
A user connects to the WebSocket.
The user sends json string to the WebSocket.
The WebSocket does things to the received message.
WebSocket finally sends the new message to all the tabs that a user have open.
The new message should be returned only to that user not others.
How can I establish one connection between a user and the WebSocket?
This is my server setup
var env = require('./config');
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var clients = [];
server.listen(env.socket.port, env.socket.host, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Websocket running at http://%s:%s', host, port);
});
app.get('/', function (req, res) {
res.send('Welcome!');
});
io.on('connection', function (socket) {
clients[] = socket;
socket.emit('chat', { hello: 'world' });
socket.on('chat', function(msg){
console.log('message: ' + msg);
sendAll(msg);
});
});
function sendAll (message) {
for (var i=0; i< clients.length; i++) {
clients[i].send("Message For All: " + message);
}
}

If you do not have authentication for the users, then you need some browser-specific piece of data to correlate users on your backend.
I don't know about cookies (haven't used them), but one way at the JavaScript level would be to store a locally generated random ID (of sufficient length so that you don't have to worry about collisions) in local storage in the browser, and transmit this as part of the initial message at the WebSocket level.

Related

Client not receiving message from server

Hi i have a node js server and im using sockets to communicate.
Index:
<script src="socket.io/socket.io.js"></script>
Client JS:
var socket = io.connect("http://localhost:8081");
socket.on('hi', function(data){
console.log("g");
console.log(data);
});
So it seems to connect just fine to the server. I have a socket called 'hi' waiting for any incoming messages. I added 2 console logs incase data was null, it would still print something to the console.
Server:
var express = require("express");
var app = express();
var server = require("http").Server(app);
var io = require("socket.io")(server);
var mazeGenerator = require("generate-maze");
app.use(express.static("public"));
io.on("connection", function(socket) { // EDITED
console.log("A player has connected - sending maze data...");
socket.emit("hi", "hi");
});
So when i refresh the page, the client connects and in my CMD i see the "A player has connected..." console log. From then on, its blank from the server or client, I can keep refreshing and it will keep saying a player has connected by the clients console stays blank
Since the connection is proven to be established, I suspect this is an issue of a way you emit the data. Your second parameter hi may not be taken as a data to be transmitted, according to
https://socket.io/docs/server-api/#socket-emit-eventname-args-ack
In my understanding, socket.io emit Object instead of String so can you try this?
io.on("connection", function(socket) {
console.log("A player has connected - sending maze data...");
socket.emit("hi", {data: "hi"});
});

JS Socket | Add full array on the site

So I have a kinda bug on my socket system. I have a array which will be emited if new connection is made to the site, but the problem is that it will be called on all users. So if I have there console.log('new user') then everyone will receive it to the console. My question is, how can I do it so the only one user who just connected receives only it?
Here is my server
io.on('connection', function(client){
clients.push(client.id);
io.emit('add games', coinflips); //This is the line
console.log(clients);
client.on('disconnect', function(){
clients.splice(client.indexOf, 1);
console.log(clients);
});
});
Here is how it's being handled
socket.on('add games', function(data){
if(data.length > 0){
addGames(data);
}
});
you can use the the socket id, socket.id then send to that id.
something along this line.
io.of('/mynamespace').sockets[socketID].emit(...)
Event this logic could work
clients = [];
then whenever a connection is made.
clients.push(socket);
then in the clients array, just index it.
clients[0].emit(...)
this is how you get a id upon connection.
console.info('Client id (id=' + socket.id + ').');
Socket.IO allows you to “namespace” your sockets, which essentially means assigning different endpoints or paths.
Namespaces are useful features to minimize the number of resources (TCP connections) and at the same time separate concerns within your application by introducing separation between communication channels. Multiple namespaces actually share the same WebSockets connection thus saving us socket ports on the server.
Namespaces are created on the server side. But they are joined by clients by sending a request to the server.
---------------------------------------------------------------
Default Namespaces
The root namespace '/' is the default namespace which is joined by clients if a namespace is not specified by the client while connecting to the server. All connections to the server using the socket object client side are made to the default namespace.
--------------------------------------------------------
Custom Namespaces
We can create our own custom namespaces. To set up a custom namespace, we can call the of function on the server-side:
---------------------------------------------------------
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
res.sendfile('index.html');
});
var nsp = io.of('/my-namespace');
nsp.on('connection', function(socket){
console.log('someone connected');
nsp.emit('hi', 'Hello everyone!');
});
http.listen(3000, function(){
console.log('listening on localhost:3000');
});

socket.io authentification not working on first connection

I have a NodeWebkit client which connects to a nodejs server using the socket.io library (JavaScript).
The client launches the connect procedure on the application start but the server does not acknoledge any connections... Though the client's socket has the connected attribute to "true".
You should know that I am using socketio-jwt to authentificate the connection.
Github: https://github.com/auth0/socketio-jwt
I know that the connection does work in a way because if I add :
io.sockets.on('connection', function(){console.log("hello");})
It prints hello !
So it seems that event though the connection is somehow made it doesn't want to do the auth part with the library, resulting in... Well... Nothing.
But that's not all !!
Because if I reboot the app (not the server) then the auth works most of the time ! It acts like a race condition... But I dont see how it could possibly be one... Every line of code is geting executed appart of the success callback of authentification.
I tried connecting to a remote server and on my localhost.
I also tried with an other library of socket auth but I've got the same probleme.
This is the server code:
var session = require('express-session');
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var socketioJwt = require('socketio-jwt');
io.sockets.on('connection', socketioJwt.authorize({
secret: 'some secret',
timeout: 15000 // 15 seconds to send the authentication message
})).on('authenticated', function (socket) {
console.log('[Info]: A user connected to socket = ', socket.decoded_token);
});
});
http.listen(5000, function () {
console.log('listening on *:5000');
});
And now the client code:
this.socket = io.connect('http://' + that.hostName +':' + that.port);
var token = jwt.sign({email: "someEail", pwd: "somePwd"}, fromServerSecret);
this.socket.on('connect', function () {
that.socket.emit('authenticate', {token: token}) //send the jwt
.on('authenticated', function () {
console.log("[Info]: Socket login successfull");
})
.on('unauthorized', function (msg) {
console.log("[Warning]: Socket unauthorized: " + JSON.stringify(msg.data));
throw new Error(msg.data.type);
});
});
The server side log "A user connected to socket" is never shown.
If you have an idear ! Thanks for your time.
Why is there a 'that' on socket.emit (client)? I think you should handle it within the same instance of socket.io - using same 'this' as above

socket.io not emitting event from server to client on connection

I have a very basic setup with socket.io but am having trouble getting my server to send back a message once the connection has been established.
When a connection is established to my server, I want the server to send back a message to the client. I've tried to accomplish this with the following code:
Server
// Modules
var fs = require('fs');
var https = require('https');
// Certificate
var options = {
pfx: fs.readFileSync('<my cert>')
};
// Create Server
httpsServer = https.createServer(options);
// Create websocket
var io = require('socket.io')(httpsServer);
// Listen on a port
httpsServer.listen(4000,function() {
console.log('listening on *:4000');
});
io.on('connection', function(socket) {
console.log('a user connected');
socket.emit('test','you connected');
});
Client
var socket = io('https://<my server>:4000');
When I execute this code, the websocket gets established and my server console shows the message "a user connected". However, the message ['test','you connected'] does not get emitted through the socket.
The only way I've been able to get this to work is to use setTimeout() to wait 500ms before emitting the event, in which case it does work.
Why is that? How can I configure my server to automatically respond with a message as soon as the user connects?
You need to listen to the emitted event, using socket.on(event, callback);
<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
<script>
var socket = io('https://localhost:4000');
//test is the emitted event.
socket.on("test", function(data){
console.log(data); //"you connected"
});
</script>

Connecting client to server using Socket.io

I'm relatively new to node.js and it's addons, so this is probably a beginnersquestion.
I'm trying to get a simple HTML page on a webserver connect to a different server running node.js with websocket.io.
My code looks like this:
Client
<script src="socket.io/socket.io.js"></script>
<script>
// Create SocketIO instance, connect
var socket = new io.Socket();
socket.connect('http://127.0.0.1:8080');
// Add a connect listener
socket.on('connect',function() {
console.log('Client has connected to the server!');
});
// Add a connect listener
socket.on('message',function(data) {
console.log('Received a message from the server!',data);
});
// Add a disconnect listener
socket.on('disconnect',function() {
console.log('The client has disconnected!');
});
// Sends a message to the server via sockets
function sendMessageToServer(message) {
socket.send(message);
};
</script>
Serverside
// Require HTTP module (to start server) and Socket.IO
var http = require('http');
var io = require('socket.io');
var port = 8080;
// Start the server at port 8080
var server = http.createServer(function(req, res){
// Send HTML headers and message
res.writeHead(200,{ 'Content-Type': 'text/html' });
res.end('<h1>Hello Socket Lover!</h1>');
});
server.listen(port);
// Create a Socket.IO instance, passing it our server
var socket = io.listen(server);
// Add a connect listener
socket.on('connection', function(client){
console.log('Connection to client established');
// Success! Now listen to messages to be received
client.on('message',function(event){
console.log('Received message from client!',event);
});
client.on('disconnect',function(){
clearInterval(interval);
console.log('Server has disconnected');
});
});
console.log('Server running at http://127.0.0.1:' + port + '/');
Starting up the server works fine and running http://localhost:8080 in my browser also works, returning 'Hello Socket Lover' as expected. But I want to make a different page talk to the sockets, not run one from node.js.
But when I run it, nothing happens and the Chrome console returns:
Failed to load resource http://undefined/socket.io/1/?t=1333119551736
Failed to load resource http://undefined/socket.io/1/?t=1333119551735
I've been at this all day. Any help?
Have you tried loading the socket.io script not from a relative URL?
You're using:
<script src="socket.io/socket.io.js"></script>
And:
socket.connect('http://127.0.0.1:8080');
You should try:
<script src="http://localhost:8080/socket.io/socket.io.js"></script>
And:
socket.connect('http://localhost:8080');
Switch localhost:8080 with whatever fits your current setup.
Also, depending on your setup, you may have some issues communicating to the server when loading the client page from a different domain (same-origin policy). This can be overcome in different ways (outside of the scope of this answer, google/SO it).
You need to make sure that you add forward slash before your link to socket.io:
<script src="/socket.io/socket.io.js"></script>
Then in the view/controller just do:
var socket = io.connect()
That should solve your problem.
Instead of:
var socket = new io.Socket();
Try:
const socket = io();
Also add a server file:
const http = require('http');
const express = require('express');
const app = express();
const server = http.createServer(app);
app.use(express.static(__dirname + '/public'));
const io = require('socket.io')(server);
const PORT = 5000;
server.listen(PORT, () => {
console.log(`Server is Listening On Port ${PORT}`);
});

Categories