Reputation: 363
I'm new to socket.io I would like to know how do i add username in this simple chat using socket.io. Thanks in advance guys. I would like to learn socket programming.
The code below is my server.js
//chat service
io.sockets.on('connection', function (socket) {
socket.on('sendMessage', function (data) {
socket.broadcast.emit('message', data);
socket.emit('message', { text: data.text });
});
});
This is my chat client index.html
<!-- index.html -->
<html>
<body>
<script src="/socket.io/socket.io.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>
$(document).ready(function () {
var socket = io.connect('http://localhost');
socket.on('message', function (data) {
$('#chat').append( '<b>' + data.text + '</b>' + '<br />');
});
$('#send').click(function () {
socket.emit('sendMessage', { text: $('#text').val() });
$('#text').val('');
});
$('#text').keypress(function(event) {
if(event.keyCode == 13) {
$('#send').click();
$('#text').val('');
}
});
});
</script>
<div id="chat" style="width: 500px; height: 300px; border: 1px solid black">
</div>
<input type="text" name="text" id="text">
<input type="button" name="send" id="send" value="send">
</body>
</html>
Upvotes: 6
Views: 27376
Reputation: 57155
To add usernames to messages most simply, add the username to the messages from client to server:
Client:
socket.emit("chat message", {username, message});
socket.on("chat message", ({username, message}) => {
console.log(username, message);
});
Server:
io.on("connection", socket => {
socket.on("chat message", data => {
// send to all clients but the sender
socket.broadcast.emit("chat message", data);
});
});
If you want to "register" a username once, you can keep a variable in each io.on("connection" ...
closure in the server code, then use a "register username"
message to let the client communicate their username (or assign one for them on the server, or optionally negotiate a valid username with a series of messages):
server.js
:const express = require("express"); // "^4.17.2"
const app = express();
const server = require("http").createServer(app);
const io = require("socket.io")(server); // "^4.4.1"
app.use(express.static("public"));
io.on("connection", socket => {
let username = "anonymous";
socket.on("chat message", message => {
io.emit("chat message", {username, message});
});
socket.on("register username", newUsername => {
username = newUsername;
});
});
server.listen(3000, () => console.log("server listening on port 3000"));
public/index.html
:<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.4.1/socket.io.js"></script>
</head>
<body>
<ul id="messages"></ul>
<form id="message-form">
<input autocomplete="off" />
<input type="submit" value="send">
</form>
<script>
const randomStr = (n=10) => [...Array(n)]
.map(e => String.fromCharCode(~~(Math.random() * 26) + 97))
.join("")
;
const username = prompt("what's your nickname?") || randomStr();
const socket = io.connect();
const messagesContainer = document.querySelector("#messages");
socket.on("connect", () => {
socket.emit("register username", username);
});
socket.on("chat message", ({username, message}) => {
const li = document.createElement("li");
li.textContent = `[${username}] ${message}`;
messagesContainer.appendChild(li);
});
document.querySelector("#message-form")
.addEventListener("submit", e => {
e.preventDefault();
if (e.target.elements[0].value) {
socket.emit("chat message", e.target.elements[0].value);
e.target.reset();
}
})
;
</script>
</body>
</html>
For apps that need access to all active users from every socket closure, you can add the usernames to an object in a shared scope.
Here's a minimal proof of concept of using an object with the mapping socket.id => username
:
public/index.html
:(mostly the same as above with the following additions)
<!-- ... -->
<h3>current users:</h3>
<ul id="users"></ul>
<!-- ... -->
<script>
// ...
const usersEl = document.querySelector("#users");
socket.on("users", ({users}) => {
usersEl.innerHTML = "";
for (const user of users) {
const li = document.createElement("li");
li.textContent = user;
usersEl.appendChild(li);
}
});
// ...
</script>
<!-- ... -->
server.js
:// ...
const usersBySocketId = {};
io.on("connection", socket => {
socket.on("disconnect", () => {
delete usersBySocketId[socket.id];
io.emit("users", {users: Object.values(usersBySocketId)});
});
socket.on("chat message", message => {
io.emit("chat message", {username: usersBySocketId[socket.id], message});
});
socket.on("register username", username => {
usersBySocketId[socket.id] = username;
io.emit("users", {users: Object.values(usersBySocketId)});
});
});
// ...
In a more complex app, there's usually additional data you want to store on the object. Sometimes a reverse mapping of usernamme => socket.id
is useful too.
I haven't validated username uniqueness or other properties, but that's another typical requirement that adds some complexity.
Upvotes: 2
Reputation: 11214
Have a look here - http://www.tamas.io/2013/05/19/simple-chat-application-using-node-js-and-socket-io/
The easiest way is to add a people's object - see the source code (link in the article).
If you want to implement rooms as well, read this: http://www.tamas.io/2013/05/19/simple-chat-application-using-node-js-and-socket-io/
Have fun.
Upvotes: 5