I made a simple app that uses socket.io for sending messages.
Here the server code piece:
var io = require('socket.io')(http);
io.on('connection', function(socket) {
console.log('a user connected');
socket.on('disconnect', function() {
console.log('user disconnected');
});
socket.on('connect to room', function(rooms) {
for (var i = 0; i < rooms.length; i++) {
socket.join(i);
console.log('joined to room number ' + i);
}
});
socket.on('chat message', function(id, msg) {
console.log('message!');
io.broadcast.to(id).emit('chat message', msg);
});
});
And here is the client code:
var socket = io('http://localhost:8080');
socket.on('connect', function(socket) {
console.log('you have been connected!');
});
socket.on('chat message', function(msg) {
console.log('message!');
$('#messages').append(msg);
});
socket.emit('connect to room', [{
{
user.rooms
}
}]);
if (e.which == 13 && target.is('#message')) {
var message_text = $('#message').val();
socket.in(room.id).emit(message_text);
$(#messages).append(message_text);
}
(The room object is the current opened room)
After I ran it I got an error:
Uncaught TypeError: socket.in is not a function
Have any ideas? If you think that I wrote something wrong, feel free to say it (for example x++ instead x += 1).
socket.in or socket.to not working in client and you should use it in server side.
Socket.io Documentation
for example :
io.on('connection', (socket) => {
// to one room
socket.to('others').emit('an event', { some: 'data' });
// to multiple rooms
socket.to('room1').to('room2').emit('hello');
// a private message to another socket
socket.to(/* another socket id */).emit('hey');
// WARNING: `socket.to(socket.id).emit()` will NOT work, as it will send to everyone in the room
// named `socket.id` but the sender. Please use the classic `socket.emit()` instead.
});
It will be socket.to('some room').emit('some event');
Refer: socket-io docs
So, I've been trying to write this chat-app for awhile now with Node.js, express,js and socket.io and everything works well. Apart from the fact that I'm trying to include a bot called Steve. Steves purpose is to welcome you to the chat, or to have him join after you've joined and introduce himself. As well as beeing able to reply to some "commands". Hi, How are you etc. Etc.
But that part is somethin that I can't get to work.
I'm not asking of you to write the code for me. But if you could please tell me if I'm on the right track and maybe come with some ideas, tips etc. I'm stuck.
Thanks in advance.
Here's my index.js
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io').listen(server);
users = [];
connections = [];
server.listen(process.env.PORT || 3000);
console.log('Server running...');
app.use(express.static(__dirname + '/public'));
app.get('/public', function(req, res) {
res.sendFile(__dirname + 'index.html')
});
io.sockets.on('connection', function(socket) {
connections.push(socket);
console.log('Connected: %s sockets connected', connections.length);
// Disconnect
socket.on('disconnect', function(data) {
users.splice(users.indexOf(socket.username), 1);
updateUsernames();
connections.splice(connections.indexOf(socket), 1);
console.log('Disconnected: %s sockets connected', connections.length);
});
// Send Message
socket.on('send message', function(data) {
io.sockets.emit('new message', {msg: data, user: socket.username});
});
<code>
// New User
socket.on('new user', function(data, callback){
callback(true);
socket.username = data;
users.push(socket.username);
updateUsernames();
});
function updateUsernames() {
io.sockets.emit('get users', users);
}
});
And here's my script.js
$(function () {
var socket = io.connect();
var $messageForm = $('#messageForm');
var $message = $('#message');
var $chat = $('#chat');
var $messageArea = $('#messageArea');
var $userFormArea = $('#userFormArea');
var $userForm = $('#userForm');
var $users = $('#users');
var $username = $('#username');
var name = 'Steve', adress = 'localhost:3000', socket;
function join(){
socket.on('new user', name);
socket.emit('message', "Hi! I am Steve. Steve the Chatter!");
socket.on('new message', listener);
};
function listener(data){
if(data.message=='Hi')
socket.emit('message', 'Hi, '+$username+'.');
};
join();
$messageForm.submit(function(e) {
e.preventDefault();
socket.emit('send message', $message.val());
$message.val('');
});
socket.on('new message', function(data) {
$chat.append('<div class="well"><strong>'+data.user+'</strong>: '+data.msg+'</div>');
});
$userForm.submit(function(e) {
e.preventDefault();
socket.emit('new user', $username.val(), function(data) {
if(data) {
$userFormArea.hide();
$messageArea.show();
}
});
$username.val('');
});
socket.on('get users', function(data) {
var html = '';
for(i = 0;i < data.length;i++){
html += '<li class="list-group-item">'+data[i]+'</li>'
;
}
$users.html(html);
});
});
I'm having problems with socket.io.
I try to create a single socket connection where this is connected to multiple rooms.
This is my current code:
function JoinRoom(id){
socket = io(domain);
socket.on('connect', function (data) {
console.log('Connected to ' + room);
socket.emit('room', room);
});
socket.on('message', function (data) {
console.log(data);
});
}
The problem is that if I remove the var socket.io(domain) function was not connected and do not receive data from the room.
Example:
socket = io(domain);
function JoinRoom(id){
socket.on('connect', function (data) {
console.log('Connected to ' + room);
socket.emit('room', room);
});
socket.on('message', function (data) {
console.log(data);
});
}
If I take the socket.io() function of the JoinRoom() function I do not receive messages message or anything. It does not work.
What am I doing wrong? Any solution?
On the client, create an event to indicate the access room.
On the server, apply the access logic.
Client
var socket = io('http://localhost');
function JoinRoom(data){
socket.emit("join", data);
}
var data = {
room:'ejemplo'
};
JoinRoom(data);
Server
var io = require('socket.io')(app);
io.on('connection', function(socket){
socket.on('join', function(data){
console.log(data); // data = { room: String, ...}
socket.join(data.room);
});
socket.on('leave', function(data){
socket.leave(data.room);
});
I am having trouble adding users to a room list, I can manage to do it on a global level (every user connected), but adding and removing users on a room basis, I just can't seem to grasp.
I have added a new var called
roomUsers
app.js
var express = require('express')
, app = express()
, http = require('http')
, server = http.createServer(app)
, io = require('socket.io').listen(server);
server.listen(8080);
// routing
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
// usernames which are currently connected to the chat
var usernames = {};
// usernames which are currently connected to the chat
var roomUsers = {};
// rooms which are currently available in chat
var rooms = ['room1','room2','room3'];
io.sockets.on('connection', function (socket) {
// when the client emits 'adduser', this listens and executes
socket.on('adduser', function(username){
// store the username in the socket session for this client
socket.username = username;
// store the room name in the socket session for this client
socket.room = 'room1';
// add the client's username to the global list
usernames[username] = username;
// send client to room 1
socket.join('room1');
// echo to client they've connected
socket.emit('updatechat', 'SERVER', 'you have connected to room1');
// echo to room 1 that a person has connected to their room
socket.broadcast.to('room1').emit('updatechat', 'SERVER', username + ' has connected to this room');
socket.emit('updaterooms', rooms, 'room1');
// update the list of users in chat,client side
io.sockets.emit('updateUsers', usernames);
//
//io.sockets.in(socket.room).emit('updateUsers', usernames);
});
// when the client emits 'sendchat', this listens and executes
socket.on('sendchat', function (data) {
// we tell the client to execute 'updatechat' with 2 parameters
io.sockets.in(socket.room).emit('updatechat', socket.username, data);
});
socket.on('switchRoom', function(newroom){
socket.leave(socket.room);
socket.join(newroom);
socket.emit('updatechat', 'SERVER', 'you have connected to '+ newroom);
// sent message to OLD room
socket.broadcast.to(socket.room).emit('updatechat', 'SERVER', socket.username+' has left this room');
delete usernames[socket.username];
// update socket session room title
socket.room = newroom;
socket.broadcast.to(newroom).emit('updatechat', 'SERVER', socket.username+' has joined this room');
socket.emit('updaterooms', rooms, newroom);
io.sockets.emit('updateUsers', usernames);
});
// when the user disconnects.. perform this
socket.on('disconnect', function(){
// remove the username from global usernames list
delete usernames[socket.username];
// update list of users in chat, client-side
io.sockets.emit('updateUsers', usernames);
// echo globally that this client has left
socket.broadcast.emit('updatechat', 'SERVER', socket.username + ' has disconnected');
socket.leave(socket.room);
});
});
Is there any advice on where I am going wrong with io.sockets.emit('updateUsers', usernames); and delete usernames[socket.username]; (obviously I need to change that to roomUsers)
frontend.js
var socket = io.connect('http://localhost:8080');
// on connection to server, ask for user's name with an anonymous callback
socket.on('connect', function(){
// call the server-side function 'adduser' and send one parameter (value of prompt)
socket.emit('adduser', prompt("What's your name?"));
});
// listener, whenever the server emits 'updatechat', this updates the chat body
socket.on('updatechat', function (username, data) {
$('#conversation').append('<b>'+username + '></b> ' + data + '<br>');
});
// listener, whenever the server emits 'updateusers', this updates the username list
socket.on('updateUsers', function(data) {
$('#users').empty();
$.each(data, function(key, value) {
$('#users').append('<div>' + key + '</div>');
});
});
// listener, whenever the server emits 'updaterooms', this updates the room the client is in
socket.on('updaterooms', function(rooms, current_room) {
$('#rooms').empty();
$.each(rooms, function(key, value) {
if(value == current_room){
$('#rooms').append('<div>' + value + '</div>');
}
else {
$('#rooms').append('<div>' + value + '</div>');
}
});
});
function switchRoom(room){
socket.emit('switchRoom', room);
}
// on load of page
$(function(){
// when the client clicks SEND
$('#datasend').click( function() {
var message = $('#data').val();
$('#data').val('');
// tell server to execute 'sendchat' and send along one parameter
socket.emit('sendchat', message);
});
// when the client hits ENTER on their keyboard
$('#data').keypress(function(e) {
if(e.which == 13) {
$(this).blur();
$('#datasend').focus().click();
}
});
});
index.html
<script src="/socket.io/socket.io.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script src="http://localhost:8888/chat/js/frontend.js"></script>
<div style="float:left;width:100px;border-right:1px solid black;height:300px;padding:10px;overflow:scroll-y;">
<b>ROOMS</b>
<div id="rooms"></div>
</div>
<div style="float:left;width:100px;border-right:1px solid black;height:300px;padding:10px;overflow:scroll-y;">
<b>USERS</b>
<div id="users"></div>
</div>
<div style="float:left;width:300px;height:250px;overflow:scroll-y;padding:10px;">
<div id="conversation"></div>
<input id="data" style="width:200px;" />
<input type="button" id="datasend" value="send" />
</div>
You should define add/remove functions inside users.js under utils folder and then import it to the app.js.
users.js
let users = [];
const addUser = ({ id, username, room }) => {
// Clean the data
username = username.trim().toLowerCase();
room = room.trim().toLowerCase();
// always validate the data
if (!username || !room) {
return {
error: "Username and room are required!"
};
}
// Check for existing user
const userExist = users.find(user => {
return user.room === room && user.username === username;
});
// Validate username
if (userExist) {
return {
error: "Username is in use!"
};
}
// Store user
const user = { id, username, room };
users.push(user);
return { user };
};
const removeUser = id => {
const index = users.findIndex(user => {
user.id === id;
});
if (index !== 1) {
//splice method returns the removed the user
return users.splice(index, 1);
}
};
module.exports = { addUser, removeUser};
Users are added, when they submitted the login form and joined the room. And we need removedUser to send disconnected users who are in particular room.
app.js
const { addUser, removeUser} = require("./utils/users");
//a simple utility function that send text and date
const { sendMessage } = require("./utils/messages");
io.on("connection", socket => {
//once user submitted the form, server receives the username and room info. data={username,room}
socket.on("join", (data, callback) => {
//if you check addUser function it either returns error or user
const { error, user } = addUser({ id: socket.id, ...data });
if (error) {
return callback(error);
}
//if there is no error, user joins the room
socket.join(user.room);
//send this generated message to the connected users
socket.emit("message", sendMessage("Admin", "Welcome!"));
//user broadcast to send info all users in the room but the last joined
socket.broadcast
.to(user.room)
.emit(
"message",
sendMessage("Admin", `${user.username} has joined!`)
);
callback();
});
socket.on("disconnect", () => {
//socket.id is generated by socket upon connection
const user = removeUser(socket.id);
if (user) {
io.to(user.room).emit(
"message",
sendMessage("Admin", `${user.name} has left`)
);
}
});
/utils/messages.js
const generateMessage = function(username, text) {
return {
username,
text,
created: new Date().getTime()
};
};
module.exports = { generateMessage };
When my node application restarted from command line or restarted by forever.js (if changes detected), then socket.io 'disconnect' event not fired.
My code is as follows :
io.sockets.on('connection', function(socket) {
var session = socket.handshake.session;
socket.join('room');
socket.on('disconnect', function() {
var clients = io.sockets.clients('room');
if (!clients || (clients && clients.length === 0)) {
//remove from online list
}
});
socket.on('error', function(err) {
if(err === 'handshake error') { console.log('handshake error', err); }
else { console.log('io error', err); }
});
socket.on('message', function(data) {
//console.log('messege received on server is "' + data + '"');
});
});
Here my socket.on('disconnect') not firing when node.js application is started.
Any guess, why it is not happening/firing?