How can I get the hostname of a socket? - node.js

When I receive a certain event from a connected socket, I have to send a request with as parameter my hostname and port. I was hoping to be able to retrieve this information from the socket object. Unfortunately, there is little documentation on this and I can't seem to be able to find out if and how this is possible.
So, is it possible to do something like this in Socket.io:
io.sockets.on('connection', function(socket){
console.log(socket.manager.server.hostname)
})'
(Or, alternatively: which thinking error am I making here in thinking that this should be possible in the first case?)

try this:
console.log(socket.handshake.headers.host);
split port if necessary:
console.log(socket.handshake.headers.host.split(":").shift());

The accepted answer does not work anymore in 2022.
Today this information can be accessed like this:
const socket = io()
socket.on('connect', () => {
console.log('Socket is connected with', this.socket.io.uri)
})

Related

How to set id of a socket in WebSocket?

I'm using: https://github.com/websockets/ws as websockets.
In socket.io you could give an id to your sockets like:
io.emit('id','myText');
io.on('id',function(data){
//read data
});
In websocket on the server you can read sockets by id.
ws.on('id', function (data) {
};
You can read sockets by id on the client too.
ws.addEventListener('id', function (data) {
};
But I couldn't find how to send a socket with a specific id, I've also checked the code base. Am I missing something or is this impossible? Or are there some hacks that could achieve this?
//I want this:
ws.send('id','myText');
I'll format my comments into an answer since it appears to have explained things for you:
There is no handler for your own message names like this in webSocket:
ws.on('id', function(data) { ... });
Instead, you listen for data with this:
ws.on('message', function(data) { ... });
If you want to send a particular message name, you send that inside the data that is sent. For example, data could be an object that you had data.messageName set to whatever you want for each message.
It appears like you're trying to use a socket.io API with a webSocket. That simply doesn't work. socket.io adds a layer on top of webSocket to add things like message names. If you want to use that type of layer with a plain webSocket, you have to implement it yourself on top of a webSocket (or just use socket.io at both ends).

Socket.IO: connection to a non-existing namespace

First post, i'll try to be as clear as possible :)
I'm trying to create on Demand namespaces on my SocketIO/NodeJS App.
Basically, the server create a specific namespace for each client.
I need to handle, server side, the case where the client try accessing a non-existing namespace.
The idea is to avoid any unwanted connection server-side, or at least, handle it to force the disconnection.
But while testing, it seems that when i try this, on client Side :
var socket = io("thisNameSpaceDontExist");
socket.on('connect', function(){
window.console.log('connected to server');
})
The 'connect' event won't trigger, which seems perfect !
Doing a console.log on socket, it displays this:
connected: false
disconnected: true
But the main problem, is that, Server Side, it's different, there is an active connection...
While doing some research, i found this issue https://github.com/Automattic/socket.io/issues/1867, still, i'm on the last version at this time: 1.3.5
for information, the socketIOHandler code i'm using:
io.on('connection', function (socket) {
console.log("[SocketIOHandler::Connection] +1");
socket.on('disconnect', function () {
console.log("[SocketIOHandler::Disconnection] -1");
});
});
PS:
Also find some issues and MR claiming the support of dynamic namespaces: https://github.com/Automattic/socket.io/issues/1854, but these are not merged, so i don't really understand the behavior on my code...
Thank you!

Sending some state with first connection in Socket.io

I am using socket.io and am looking for a way for the client to be able to specify which room it would like to connect to, but I can't figure out a good way to make this happen.
On the server I have:
io.sockets.on 'connection', (socket)->
console.log 'A socket connected.'
socket.join('my_room')
On the client I have:
io = io.connect("http://domain.com")
What I would like to do is get some initial state in the first connection on the client so that the server knows which room it should try and connect the person to.
So something like this on the client:
io = io.connect("http://domain.com", room_1)
Then the server would have some thing like this:
io.sockets.on 'connection', (socket, data)->
console.log 'A socket with connected!'
socket.join(data)
Is this possible to do with room? Is there a better way? I looked into namespaces but rooms more closely fit what I am trying to do.
I agree with drinchev. You should just send the data on the connect event on the client side.
io = io.connect 'http://domain.com'
io.on 'connect', () ->
socket.emit('join-room', room_1)
Another option is to use socket.io namespaces. This will allow you to avoid the round trip, but there are some differences between namespaces and channels and you will have to determine which makes more sense for your app.
io = io.connect 'http://domain.com/room_1'
The accepted answer here has a good rundown of the differences between channels and namespaces. socket.io rooms or namespacing?

What's the correct way to pass a Socket.IO socket between modules?

At the moment I have a getter/setter socket module as follows
var socket;
module.exports.getSocket = getSocket;
module.exports.setSocket = setSocket;
function getSocket() {
return socket;
}
function setSocket(sock) {
if (undefined == socket) socket = sock;
}
In app.js I set as follows
var sio = require('./lib/socket');
var io = require('socket.io').listen(app);
io.sockets.on('connection', function (socket) {
sio.setSocket(socket);
});
In my module I use as follows
sio = require('./lib/socket');
socket.getSocket().broadcast.emit(...);
It seems a bit contrived is there a better way to do this?
Edit: I would like a general solution to the problem of firing off a message which is not initiated by the client socket. For example suppose I retrieve stock prices from an external source and wish to fire an event on price update. Since it is not client initiated, how can I get access to the socket? Or alternatively let's say I wish to fire off a socket message in response to a POST request. Once again I'm not sure how I would access the socket.
There are a number of options for sharing the socket, but it would help to know more about what your module is going to do. Without knowing more, I would recommend you just pass the socket to the module via the function you are calling instead of trying to use some shared state.
If you need to use a shared state (you're trying to send messages to specific users triggered by something other than a socket message) then I would recommend sticking with an established session framework and just persist the socket id. You can get the correct socket just using the id.
See this answer for how to use socket.io with sessions: socket.io and session?
Add some more details and I'll revise my answer.
UPDATE
If you are just trying to broadcast to everyone who is connected, you do not need a socket handle. From any module that references socket.io, you can call io.sockets.emit('stuff').

List of connected clients username using socket io

I've made a chat client with different chat rooms in NodeJS, socketIO and Express. I am trying to display an updated list over connected users for each room.
Is there a way to connect a username to an object so I could see all the usernames when I do:
var users = io.sockets.clients('room')
and then do something like this:
users[0].username
In what other ways can I do this?
Solved:
This is sort of a duplicate, but the solution is not written out very clearly anywhere so I'd thought I write it down here. This is the solution of the post by Andy Hin which was answered by mak. And also the comments in this post.
Just to make things a bit clearer. If you want to store anything on a socket object you can do this:
socket.set('nickname', 'Guest');
sockets also has a get method, so if you want all of the users do:
for (var socketId in io.sockets.sockets) {
io.sockets.sockets[socketId].get('nickname', function(err, nickname) {
console.log(nickname);
});
}
As alessioalex pointed out, the API might change and it is safer to keep track of user by yourself. You can do so this by using the socket id on disconnect.
io.sockets.on('connection', function (socket) {
socket.on('disconnect', function() {
console.log(socket.id + ' disconnected');
//remove user from db
}
});
There are similar questions that will help you with this:
Socket.IO - how do I get a list of connected sockets/clients?
Create a list of Connected Clients using socket.io
My advice is to keep track yourself of the list of connected clients, because you never know when the internal API of Socket.IO may change. So on each connect add the client to an array (or to the database) and on each disconnect remove him.
In socket.io#2.3.0 you can use:
Object.keys(io.sockets).forEach((socketId) => {
const socket = io.sockets[socketId];
})

Resources