0

I have used methods socket.on and io.emit, And i got response to all users. But, i want to get response for particular user.

But my application contains login functionality and i followed this post on stackoverflow, and they are saying we need unique userId and socketId in an object for a particular user to emit an event for a particular user. But i am getting the userId after login, But we want it when user connect to app.

So can anyone please help me with the same?

Rajat
  • 486
  • 1
  • 10
  • 35

2 Answers2

1
  1. In your node.js, create a global array 'aryUser', each element contains the socketid and loginid.

  2. node.js onConnect (new connection), add a new element to the array with the socketid and set loginid = empty.

  3. after the user login, emit an event from client to the server, e.g:

socket.emit('userloginok', loginid)

  1. in node.js, define a function:

socket.on('userloginok', loginid)

and in this function, search the aryUser with the socketid and replace the empty loginid inside the array element with the parm loginid.

  1. in node.js, define the function:

socket.on('disconnect')

and in this function, search the aryUser, use aryUser.splice(i,1) to remove the user just disconnected.

that means, aryUser contains all users connected, some of them logined, some of them not logined. And you can use the socketid of the array to send message to particular user, and/or all users.

Example Source Code:

  1. server.js

http://www.zephan.top/server.js

  1. server.html

http://www.zephan.top/server.html.txt

rename server.html.txt to server.html, put server.html and server.js in the same directory, and run:

node server.js

Kenneth Li
  • 1,632
  • 1
  • 14
  • 19
  • Thanks for quick response. Your answer looks good but i didn't got one thing here. "search the aryUser with the socketid". I didn't get this point. Can you please explain it little bit more? – Rajat Jan 13 '19 at 15:08
  • in the node.js, when you define a function socket.on('SomeFunctionToBeCalledByClient', SomeDataFromClient), and inside this function, there is a 'predefinded, unique system variable', namely: socket.socketid, which help you to identify which client is actually calling your function, so you can store this id to the Global array. – Kenneth Li Jan 13 '19 at 15:14
  • i.e. you can use socket.socketid inside socket.on('connect'/'disconnect'/'anything') – Kenneth Li Jan 13 '19 at 15:17
  • @KennethLi, On 3rd point you said. emit event from client to server after login, But how user got socket Id at client? As it is available on server only. –  Jan 13 '19 at 15:23
  • I'm using mobile phone right now, you may try to go to this website, which is created by my student Zephan: https://thisapp.zephan.top This web site/app is created by cordova, it's an exercise for my student, which is a Whatsapp like app. You may try it by registering your own user id, or use test ids, test1 and test2, with password: qwerty. – Kenneth Li Jan 13 '19 at 15:24
  • then you can chat with yourself. If you are using Android phone, you can also download the apk: – Kenneth Li Jan 13 '19 at 15:25
  • when I have a pc, i can copy and paste Some of the codes in the answer – Kenneth Li Jan 13 '19 at 15:27
  • I am having the same problem. @KennethLi, Please help us to just in "How to manage users on connection and disconnect". We just want to know it. –  Jan 13 '19 at 15:34
  • Suppose there are N users connect at the same time, socket.on('connect') will be called N times (something like multi-thread), each call will have a different socket.socketid. same for socket.on('userloginok', login), it will be called PER LOGIN. What do you mean 'send the connected user to client side'? – Kenneth Li Jan 14 '19 at 06:35
  • pls. check my updated answer with sample source code. I'm unable to reformat the source code and include it in the answer, so you have to download it. – Kenneth Li Jan 14 '19 at 08:24
0

Yes, you definitely need socketId in order to send and receive messages between two specific users.

UserId is required just to keep track of socketId associated with the particular user or you can manage it with some other way as well that's up to you.

As per your question, you have userId of the user and you need socketId of that user! So, in this case, you can pass userId when that particular connects to a socket server from the client side as shown in below snippet,

const socket = io(this.SOCKET_SERVER_BASE_URL, { query: `userId=${userId}` });

And you can read this user on nodejs server like this,

const userId= socket.request._query['userId'],
const socketId= socket.id

Now store this socketId in somewhere, for example, Redis or some sort of caching mechanism again up to you, just make sure fetching and retrieval should be fast.

Now while sending a message just pull the socketId from your cache and emit the message on that socketId by using below code,

io.to(socket.id).emit(`message-response`, {
    message: 'hello'
 });

I have written a complete blog post on this topic on both Angular and AngularJs, you can refer those as well.

Edit 1:

Part 1 => When your user completes the login request, then make the connection to the socket server. Assuming you are using React Or Angular After a successful login you will redirect your user to home component(page). On the Home component(page) make the socket server connect by passing the userId just like this,

const socket = io(SOCKET_SERVER_BASE_URL, { query: `userId=${userId}` });

P.S. you can get userID from URL or maybe using a cookie that is up to you.

Once you receive this socket connection request on the server, then you can read the userID query and you can get socketId associated with it and store it in cache like this,

io.use( async (socket, next) => {
    try {
        await addSocketIdInCache({
            userId: socket.request._query['userId'],
            socketId: socket.id
        });
        next();
    } catch (error) {
        // Error
        console.error(error);
    }
});

Part 2 => Now, let's say you have a list of the users on the client side, and you want to send a message to particular users.

socket.emit(`message`, {
    message: 'hello',
    userId: userId
 });

On the server side, fetch the socketId from the cache using UserId. Once you get the socketId from cache send a specific message like this,

io.to(socketId).emit(`message-response`, {
    message: 'hello'
 });

Hope this helps.

Shanky
  • 101
  • 1
  • 1
  • 8
  • As i said, I am getting userId when user login to app. But socketId will get instantly after client connects with server. your answer is totally unclear. Can you please explain with example? – Rajat Jan 22 '19 at 16:40