Socket IO emit an event to specific users – Node JS

Introduction

Sockets are used for real-time communication. They are now being used in chat apps, team collaboration tools, and many more. Socket IO emit events to the receivers and the receivers are constantly listening to that event. When the event is received on the client-side, they can perform the necessary action. You can attach as many event listeners as you want and perform different actions for each event.

Users are connected with a Node JS server using a client-side library called Socket IO. Users can also join the room which will be helpful if you are creating a group chat app. There are 4 ways in which socket events are fired.

  1. Send event to all connected users, including the sender.
  2. Send event to all users, except the sender.
  3. Emit event to all users in a room.
  4. Send event to specific users.

In this tutorial, we will be covering the 4th part i.e. send socket events to specific users.

Video tutorial:

Problem

Suppose you have a chat app where you want 2 people to have a private chat. Now you want to have a real-time effect i.e. to show the new messages without having to refresh the page. This requires sockets that send the data in real-time. And we can show the data on the client-side in real-time too. Now when a sender sends a message to a specific user, we need to send the socket event to that specific user only.

Solution

We will create a simple script that allows us to send events to a specific user only. You can then integrate and customize that logic in your project. First, you need to download and install Node JS. You also need to download the Socket IO JS client-side library. We will have a simple database from where we can show all the users in a list, with a button to send an event to that user only. So we need to create a database with a simple users table, you can use your own database as well.

Database

In your phpMyAdmin, create a database named “send_socket_event_to_specific_users”. In that database, create a users table:

CREATE TABLE `users` (
  `id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `name` text NOT NULL
);

Add few rows in that table so we can show them in a list or a table.

INSERT INTO `users` (`id`, `name`) VALUES
(1, 'Adnan'),
(2, 'Afzal'),
(3, 'John'),
(4, 'Doe');

Then in your index.php, show all users.

<?php
	$conn = new PDO("mysql:host=localhost:3306;dbname=send_socket_event_to_specific_users", "root", "");
	$sql = "SELECT * FROM users";
	$result = $conn->prepare($sql);
	$result->execute([]);
	$users = $result->fetchAll();
?>

<table>
	<thead>
		<tr>
			<th>ID</th>
			<th>Name</th>
			<th>Action</th>
		</tr>
	</thead>

	<tbody>
		<?php foreach ($users as $user): ?>
			<tr>
				<td><?php echo $user['id']; ?></td>
				<td><?php echo $user['name']; ?></td>
				<td>
					<form method="POST" onsubmit="return sendEvent(this);">
						<input type="hidden" name="id" value="<?php echo $user['id']; ?>" required />
						<input type="submit" value="Send Message" />
					</form>
				</td>
			</tr>
		<?php endforeach; ?>
	</tbody>
</table>

It will show all users in a table with a button to send message. Now when the page loads, we need to get the ID of the user, you can also get it from PHP sessions.

Include Socket IO library

Before that, we need to include the Socket IO JS library. You can download it from here.

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

<script>
	var userId = prompt("Enter user ID");

	var socketIO = io("http://localhost:3000");
	socketIO.emit("connected", userId);
</script>

It will store your ID in userId variable. And it will connect with Node JS server and emit an event “connected” with your ID.

Now we need to create a simple Node server. Create an empty folder and create a file named “server.js” in it. Then open the CMD in that folder and run the following commands one-by-one:

npm init
npm install express http socket.io mysql
npm install -g nodemon
nodemon server.js

Write the following code in your server.js file:

var express = require("express");
var app = express();

var http = require("http").createServer(app);
var socketIO = require("socket.io")(http, {
	cors: {
		origin: "*"
	}
});

var users = [];

socketIO.on("connection", function (socket) {

	socket.on("connected", function (userId) {
		users[userId] = socket.id;
	});

    // socket.on("sendEvent") goes here
});

http.listen(process.env.PORT || 3000, function () {
	console.log("Server is started.");
});

This will start the server at port 3000, creates a users array and store all connected user’s socket ID in it.

Send event using socket IO emit function

Back in index.php, we need to create a JS function to send the event when the user click the “Send message” button:

function sendEvent(form) {
	event.preventDefault();

	var message = prompt("Enter message");
	socketIO.emit("sendEvent", {
		"myId": userId,
		"userId": form.id.value,
		"message": message
	});
}

Now in server.js, we need to listen to that event and send the message to that user only. But before that, we need to include mysql module because the user’s names are stored in mysql database. At the top of your server.js:

var mysql = require("mysql");
var connection = mysql.createConnection({
	host: "localhost",
	port: 3306,
	user: "root",
	password: "",
	database: "send_socket_event_to_specific_users"
});

connection.connect(function (error) {
	console.log("Database connected: " + error);
});

And after the socket connected event:

socket.on("sendEvent", async function (data) {
	connection.query("SELECT * FROM users WHERE id = " + data.userId, function (error, receiver) {
		if (receiver != null) {
			if (receiver.length > 0) {

				connection.query("SELECT * FROM users WHERE id = " + data.myId, function (error, sender) {
					if (sender.length > 0) {
						var message = "New message received from: " + sender[0].name + ". Message: " + data.message;
						socketIO.to(users[receiver[0].id]).emit("messageReceived", message);
					}
				});
			}
		}
	});
});

This will search the sender and receiver by ID, and emit the event to the receiver with the name of the sender.

Listen to socket IO events

Now we need to listen to that event in our index.php and show a message in a list when that event is received. First, create a ul where all messages will be displayed:

<ul id="messages"></ul>

Then attach that event in JS:

socketIO.on("messageReceived", function (data) {
	var html = "<li>" + data + "</li>";
	document.getElementById("messages").innerHTML = html + document.getElementById("messages").innerHTML;
});

So that’s how you can use the socket IO emit function to send the event to a specific user only.

Check out realtime chat app tutorial using socket IO.

[wpdm_package id=’1295′]

2 Replies to “Socket IO emit an event to specific users – Node JS”

Comments are closed.