• Download
  • Contact
  • Terms of Service
  • Privacy Policy
  • About US
Codershood
  • Demos
  • Plugins
  • Angular
  • NodeJs
  • GO lang
  • Others
No Result
View All Result
Codershood
  • Demos
  • Plugins
  • Angular
  • NodeJs
  • GO lang
  • Others
No Result
View All Result
Codershood
No Result
View All Result

Sending message to specific user with socket.io

by Shashank Tiwari
March 21, 2019
in NodeJs
22
5 Minutes Read
Sending message to specific user with socket.io

Sending a message to the specific user with socket.io is very important feature If you are building private Chat application. When I published Private Chat application, I mentioned that We are not sending a message to the unique socket. Instead, we were broadcasting the messages and showing to the specific user that by AngularJs.

But this article is truly based on Sending message to the specific user with socket.io and will explain how we can do that in socket.io.

 

Also, read Typing notification in chatting application using nodejs and socket.io

 Download

 

1. Sending message to the specific user with the socket.io workflow

Here we are keeping track of all the users in the array of object. When users connect to NodeJs server, then Nodejs server sends an array of object to the client as a list of online users. This object comprises of unique socket.id as well as username which is provided by the client when a client connects to the server.

for example, [ {id:'some randon id',name:'Shashank'},{...},{...}....{n}];

 

Note : In this application, I am using an array to store the users connected to the server, But In production please avoid this idea instead use your choice of database to store the user’s information.

 

The below Image shows how we are storing information of users connected to the server.

Here n number of users connected to the server, we are storing their respective socket.id, name and throwing back the array of object to all clients connected to the server.

 

sending messages to specific users with socket.io user connecting to server

To send a message to the particular client, we are must provide socket.id of that client to the server and at the server side socket.io takes care of delivering that message by using,

socket.broadcast.to('ID').emit( 'send msg', {somedata : somedata_server} );

For example,user3 want to send a message to user1. Assuming user3 is contacted from Chrome browser and user1 is connected to firefox browser as shown below image.

sending messages to specific users with socket.io

 

Here, managing Array of users plays very important role in terms of showing online users in the chat room.For example, when one user goes offline other users should get updated list of online users.The figure below explains the same have a look,

sending messages to specific user logout from server

 

 

Also, readShowing online users using Nodejs and Socket.io

2. Folder structure and package.json:

Before creating a project let’s take a look at our project folder structure.In this application, we have three main folders named as utils, views, and public_data in our application.
Folder structure:

+--- utils
|    +-- config.js
|    +---routes.js
|
+--- node_modules
|    \ body-parser
|    \ express
|    \ socket.io
|
+--- public_data
|   \ css
|       |
|       +-- bootstrap.min.css   
|       +-- style.css   
|   \ js
|       |
|       +-- angular.min.js  
|       +-- script.js 
+--- views
|    +-- index.html
|
+---server.js
+---package.json

 

Here I have 1.7.1 socket.io version installed by the time of writing this article.

Find yours, cd/dir_name/npm list socket.io

To create new nodejs, the best practice is to start with npm init. This command will create a package.json file. Here is my package.json file,

{
    "name": "sending-message-to-specific-user-with-socket-io",
    "version": "0.0.1",
    "description": "Sending message to specific user with socket.io",
    "author": "Shashank",
    "license": "MIT",
    "dependencies": {
        "express": "4.14.0",
        "body-parser": "1.15.2",
        "socket.io": "1.7.1",
        "ejs":"2.5.3"
    }
}

 

3. Creating Nodejs project

So Let’s start off by creating config.js in utils folder. This file takes care of express related configuration.
config.js :

class Config{
    
    constructor(app){
        // Setting .html as the default template extension
        app.set('view engine', 'html');

        // Initializing the ejs template engine
        app.engine('html', require('ejs').renderFile);

        // Telling express where it can find the templates
        app.set('views', (__dirname + '/../pages'));

        //Files 
        app.use(require('express').static(require('path').join('public_data')));

    }
}
module.exports = Config;

 

Now let’s create a server.js file. In this file, we will add the configuration of our application.

Server.js :

'use strict';

const express = require("express");
const http = require('http');
const socketio = require('socket.io');
const bodyParser = require('body-parser');


const routes = require('./utils/routes'); 
const config = require('./utils/config'); 


class Server{

    constructor(){
        this.port =  process.env.PORT || 81;
        this.host = `localhost`;
        
        this.app = express();
        this.http = http.Server(this.app);
        this.socket = socketio(this.http);
    }

    appConfig(){        
        this.app.use(
            bodyParser.json()
        );
        new config(this.app);
    }

    /* Including app Routes starts*/    includeRoutes(){
        new routes(this.app,this.socket).routesConfig();
    }
    /* Including app Routes ends*/  

    appExecute(){

        this.appConfig();
        this.includeRoutes();

        this.http.listen(this.port, this.host, () => {
            console.log(`Listening on http://${this.host}:${this.port}`);
        });
    }

}

const app = new Server();
app.appExecute();

 

Now the last piece of the puzzle on the server side is remaining and i.e. routes and socket event for our application. For that, we have to create one more file called as routes.js inside the utils folder.

Here,

In the appRoutes() function, we can add express routes but for now, we are just rendering the index.html file.

In the socketEevents() function, we have added the socket events.

With the help of these events,

  1. we will add the users
  2. send messages to them and
  3. delete the user from the array.

routes.js:

'use strict';

class Routes{

    constructor(app,socket){
        this.app = app;
        this.io = socket;

        /* 
            Array to store the list of users along with there respective socket id.
        */        this.users = []; 
    }


    appRoutes(){

        this.app.get('/', (request,response) => {
            response.render('index');
        });

    }

    socketEvents(){

        this.io.on('connection', (socket) => {

            socket.on('username', (userName) => {

                this.users.push({
                    id : socket.id,
                    userName : userName
                });

                let len = this.users.length;
                len--;

                this.io.emit('userList',this.users,this.users[len].id); 
            });

            socket.on('getMsg', (data) => {
                socket.broadcast.to(data.toid).emit('sendMsg',{
                    msg:data.msg,
                    name:data.name
                });
            });

            socket.on('disconnect',()=>{
                
                for(let i=0; i < this.users.length; i++){
                    
                    if(this.users[i].id === socket.id){
                        this.users.splice(i,1); 
                    }
                }
                this.io.emit('exit',this.users); 
            });

        });

    }

    routesConfig(){
        this.appRoutes();
        this.socketEvents();
    }
}
module.exports = Routes;

 

4 FrontEnd implementation

To communicate with the server, we need to add Socket.io in the client side code. we can do that by importing the socket.io script as shown below,

<script src="/socket.io/socket.io.js"></script>

After importing this script, we can call socket by writing below code,
const socket = io.connect();
Now we can communicate with the server on emitting events on top of socket constant. Let’s take a look at index.html file.

index.html

<html ng-app="app"  ng-controller="app">
    <head>
        <title>Sending message to specific client</title>
        <link rel="stylesheet" href="css/bootstrap.min.css">
        <link rel="stylesheet" href="css/style.css">
    </head>
    <body>
        <div class="container">
            <div class="row">
                <div class="col-md-4 user-list">
                <h2>List of Users</h2>
                <ul class="list-group">
                    <li class="list-group-item" 
                        ng-repeat="user in userList"
                        ng-class="{ 'active' : user.id == selectedUser}"
                        ng-click = seletedUser(user.id);
                        ng-style="{
                            'cursor': user.id === socketId ? 'not-allowed' :'pointer'
                        }"
                        >
                        <span id='{{user.id}}' >{{ user.id === socketId ? 'You': user.userName }}</span>
                    </li>
                </ul>
                    
                </div>
                <div class="col-md-8 message-box">
                    <h2>Messages sent by users</h2>
                    <div class="message-container">
                        <ul class="list-group">
                            <li class="list-group-item" 
                                ng-repeat="message in messages"
                                >
                                {{ message.name }} says: {{ message.msg }}
                            </li>
                        </ul>
                        <div class="alert alert-warning" ng-show='messages.length == 0'>
                            No messages for you.
                        </div>
                    </div>
                    <div class="message-sender">
                        <textarea class="form-control" ng-model='message' ng-keypress="sendMsg($event)"></textarea>
                    </div>
                </div>
            </div>
        </div>
    </body> 
    
    <script src="/socket.io/socket.io.js"></script>
    <script src="js/angular.min.js"></script>
    <script src="js/script.js"></script>
</html>

Now let’s write some Angular Js code make our application actually work. Create a script.js file inside the /public_data folder and write the below code.

script.js:

'use strict';

const app = angular.module('app',[]);

/* 
    Making factory method for socket 
*/app.factory('socket', function ($rootScope) {
    const socket = io.connect();
    return {
        on: function (eventName, callback) {
            socket.on(eventName, function () {  
                var args = arguments;
                $rootScope.$apply(function () {
                    callback.apply(socket, args);
                });
            });
        },
        emit: function (eventName, data, callback) {
            socket.emit(eventName, data, function () {
                var args = arguments;
                $rootScope.$apply(function () {
                    if (callback) {
                        callback.apply(socket, args);
                    }
                });
            })
        }
    };
});

app.controller('app', ($scope,socket) => {

    $scope.socketId = null;
    $scope.selectedUser = null;
    $scope.messages = [];
    $scope.msgData = null;
    $scope.userList = [];

    $scope.username = window.prompt('Enter Your Name'); 
    if ($scope.username === '') {
        window.location.reload();
    }


    $scope.seletedUser = (selectedUser) => {
        selectedUser === $scope.socketId ? alert("Can't message to yourself.") : $scope.selectedUser = selectedUser;
    };


    $scope.sendMsg = ($event) => {
        const keyCode = $event.which || $event.keyCode; 

        if (keyCode === 13 && $scope.message !== null) { 
            socket.emit('getMsg',{
                toid : $scope.selectedUser,
                msg : $scope.message,
                name : $scope.username
            });
            $scope.message = null;
        }       
    };


    socket.emit('username',$scope.username);

    socket.on('userList', (userList,socketId) => {
        if($scope.socketId === null){
            $scope.socketId = socketId;
        }
        $scope.userList = userList;
    });     


    socket.on('exit', (userList) => {
        $scope.userList = userList;
    });

    socket.on('sendMsg', (data) => {
        $scope.messages.push(data);
    });

});

 

Now using this article you can Send a message to the specific user with socket.io and you can integrate this feature in the realtime private chat application.

Further reading and links:

Socket.io rooms and namespaces

 

Tags: ChatExpressNodejsNotificationsocket.io
Previous Post

Login template using Material Design Lite (MDL)

Next Post

Integrating WordPress Chatroom using nodejs and socket.io -part 1

Related Posts

Create your first Blockchain using Nodejs Blockchain
NodeJs

Create your first Blockchain using Nodejs

September 12, 2018
Detect Faces in Images using Nodejs
NodeJs

Detect Faces in Images using Nodejs

August 8, 2018
Creating API Rate limiter in Nodejs using express and Redis
NodeJs

Creating API Rate limiter in Nodejs using express and Redis

August 8, 2018
Next Post
Wordpress chatroom integration using Nodejs and Socket.io

Integrating WordPress Chatroom using nodejs and socket.io -part 1

Comments 22

  1. Brano David says:
    9 years ago

    Is there possible send message also to offline users?

    Reply
    • Shashank says:
      9 years ago

      No you can’t bcoz user is not connected to server so you you won’t get user’s socketid.

      You can do this by storing user’s id(not socketid ) in db and store the messages too. when user comes online show those messages.

      I have covered this topic in this article.

      https://codershood.info/2015/12/10/real-time-chatting-app-using-nodejs-mysql-angularjs-and-socket-io-part-1/

      Reply
      • mohamed says:
        7 years ago

        i can’t see my messages

        Reply
  2. rupesh says:
    8 years ago

    Download link is not working please provide me a link to download

    Reply
    • Shashank says:
      8 years ago

      Hi Rupesh,
      Replied you on your email.

      Reply
  3. Leang says:
    8 years ago

    Please send me a download link

    Reply
  4. maneesh patel says:
    8 years ago

    Nice article. Some typo in tutorial.

    // Telling express where it can find the templates
    app.set(‘views’, (__dirname + ‘/../views’));

    should be

    // Telling express where it can find the templates
    app.set(‘views’, (__dirname + ‘/../pages’));

    Reply
    • Shashank says:
      8 years ago

      That’s Maneesh,
      Corrected that.

      Reply
  5. mohamed says:
    7 years ago

    i can’t see my messages

    Reply
    • Shashank says:
      7 years ago

      Okay so you can follow below steps:
      1. Check if both the clients are connected to socket server.
      2. Once connected, check if you are getting your data inside

      this.io.on('connection', (socket) => {

      and

       socket.on('getMsg', (data) => {

      method, by doing console.log();

      If still does work for you please share your code here will try to resolve it here.

      Reply
  6. mohamed says:
    7 years ago

    help me please

    Reply
  7. kratos says:
    7 years ago

    i have a problem with this method! if the app grow and then we have 100k clients using the app at the same time.
    What about the efficiency ?

    Reply
    • Shashank says:
      7 years ago

      This does not entirely depend upon the Socket.io library, You might wanna consider all your option ranging from server to overall project architecture.
      Let’s assume you have 100k connections, then yes socket.io might explode (I never tested this), so in this case, you can consider using websockets/ws it.

      Reply
  8. Chan says:
    7 years ago

    Hi – Great article…How would I go about building an offline messaging system like Airbnb. If I want to build a messaging system between guests and hosts can I use Socket.io for that? Or is that an overkill since it is more of a real time chat platform?

    Reply
  9. Ayushi Dixit says:
    7 years ago

    hi! The download link is not working. I followed the tutorial but my end product looks weird without the style.css :’)

    Reply
    • Shashank says:
      7 years ago

      strange!
      Here is a Github Link.
      Can you please tell me ,what is happening at your end why you can’t download? So I can fix the issue.

      Reply
      • Ayushi Dixit says:
        7 years ago

        https://uploads.disquscdn.com/images/255196dc5e0618a9759bd9cd48e54b63981041c5e1ded9978d846434cde60d5d.png

        Just says this when i try to open the file that i downloaded. Technically the link is working but i can’t open it. :/

        Reply
        • Shashank says:
          7 years ago

          Okay, Thanks.

          Reply
  10. Atex Olumide says:
    7 years ago

    Hi Shashank,
    Nice article. I would like to ask. why did you suggest not to use an array in production environment?

    “Note: In this application, I am using an array to store the users connected to the server, But In production please avoid this idea instead use your choice of database to store the user’s information.”

    I notice everything a uses refresh or visit another page on the same site. socket id changes. This is result in sending too many requests to the DB. What do you advise?

    Thanks

    Reply
  11. sumit says:
    5 years ago

    thanks a lot

    Reply
  12. farzan ahmedi says:
    4 years ago

    HI! Its 2021!
    Thanks for giving me great idea to create my project.
    god bless you!

    Reply
  13. Joel says:
    3 years ago

    Thanks a lot for this.

    Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *




https://codershood.info

www.codershood.info programming blog dedicated to providing high-quality coding tutorial and articles on web development, Angular, React, Laravel, AngularJs, CSS, Node.js, ExpressJs and many more. We also provide ebook based on complicated web application along with the source code.

  • Download
  • Contact
  • Terms of Service
  • Privacy Policy
  • About US

www.codershood.info is licensed under a Creative Commons Attribution 4.0 International License.

No Result
View All Result
  • Demos
  • Plugins
  • Angular
  • NodeJs
  • GO lang
  • Others

www.codershood.info is licensed under a Creative Commons Attribution 4.0 International License.