This chat application I'm working on as practice (being new to Node and Socket.IO) is doing well except for the fact that I can't get the server to broadcast messages to all the clients. I've checked for inconsistent variables (and may have created some while playing around, my apologies ;P) but it's not working? I'm confused because I'm not receiving any console errors or anything like that, making this incredibly hard to debug. Could it be that I'm running into my first encounter with how callbacks can end up nesting in an unwanted manner?
Anyway, here's some code:
App.js:
// Require dependencies
var express = require('express');
var app = express();
var http = require('http');
var server = http.createServer(app);
var io = require('socket.io').listen(server);
// Listen for connections
io.sockets.on('connection', function(client) {
console.log("Someone is connecting...");
client.on('join', function(name) {
client.set('nickname', name);
console.log(name+" has connected!");
client.broadcast.emit('connected', name + " has connected");
});
// Receive messages from the client and broadcast them to everyone
client.on('messages', function(data) {
client.get('nickname', function(err, name) {
client.broadcast.emit("chat", name + ": " + data);
});
});
});
// Without this line, the CSS will not work
app.use('/public', express.static(__dirname + '/public'));
// Route index.html to the root path
app.get('/', function(request, response) {
response.sendfile(__dirname + "/index.html");
});
// Listen for GET requests to the server
server.listen(3000);
console.log("Listening on port 3000");
index.html:
<!DOCTYPE html>
<html>
<head>
<title>Chatapp</title>
<link rel="stylesheet" type="text/css" href="public/default.css"></link>
</head>
<body>
<h1 class="title">Chatapp</h1>
<div id="wrapper">
<div id="online">
</div>
<div id="body">
<div id="status"></div>
<div id="chat">
</div>
</div>
<div id="input">
<form id="chatform">
<input type="text" id="message"></input>
<input type="submit" id="send" value="Send!"></input>
</form>
</div>
<div class="clear"></div>
</div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script>
// Wait until DOM is ready
$(document).ready(function() {
// Establish a connection to the server
var server = io.connect('http://localhost:3000');
// On submit, send the chat form message to the server, prevent default redirect and reset the chat form
$('#chatform').submit(function(e) {
e.preventDefault();
var message = $('#message').val();
server.emit('messages', message);
$('#chatform')[0].reset();
});
server.on('connect', function(data) {
nickname = prompt('What is your nickname?');
$('#status').html('Connected to Chatapp as ' +nickname);
server.emit('join', nickname);
});
server.on('connected', function(data) {
$('<p>'+data+'</p>').appendTo('#chat');
});
// Listen for messages broadcasted to every client by the server - this does not work for some reason.
server.on('chat', function(data) {
$(data).appendTo('#chat');
});
});
</script>
</body>
</html>
/public/default.css:
body {
margin: 0;
padding: 0;
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
}
a {
color: #00B7FF;
}
#wrapper {
margin: 0 auto;
width: 940px;
height: 500px;
padding: 0;
border: 1px solid #000;
}
#online {
float: left;
width: 188px;
height: 480px;
padding: 10px;
border-right: 1px solid #000;
background: #3d3d3d;
color: #eee;
box-shadow: inset 1px 1px 0px #fff, inset -1px -1px 0px #fff;
}
#body {
float: left;
width: 731px;
height: 439px;
padding: 0;
border-bottom: 1px solid #000;
}
#status {
color: #eee;
height: 30px;
border-bottom: 1px solid #000;
background: #3d3d3d;
padding-left: 10px;
line-height: 30px;
box-shadow: inset 1px 1px 0px #fff, inset -1px -1px 0px #fff;
}
#chat {
background: #c4f2eb;
height: 388px;
padding: 10px;
box-shadow: inset 1px 1px 0px #fff, inset -1px -1px 0px #fff;
}
#input {
float: left;
height: 60px;
width: 731px;
}
.clear {
clear: both;
}
h1.title {
text-align: center;
}
input#message {
float: left;
margin: 0;
width: 640px;
height: 58px;
border: none;
font-size: 28px;
padding-left: 10px;
box-shadow: inset 1px 1px 3px rgba(0,0,0,0.3);
}
input#message:focus {
border: none;
outline: none;
box-shadow: inset 1px 1px 3px #55ba57, inset -1px -1px 3px #55ba57;
}
input#send {
float: left;
background: #55ba57;
color: #fff;
border: none;
height: 60px;
margin: 0;
width: 81px;
border-left: 1px solid #000;
box-shadow: inset 1px 1px 0px #fff, inset -1px -1px 0px #fff;
}
input#send:hover {
background: #489949;
cursor: pointer;
}
input#send:active {
background: #1e7520;
}
OK, let's break this problem up into many little sub-problems ;)
When you say you can't log (or alert) data
, at which point are you trying this? (Problem from your comments)
If this is in server.on('connect', function(data) {...
you'll never get any data. The connect
event is purely informational.
Both of these do not send the data back to the client who connected\chat
s.
client.broadcast.emit('connected', name + " has connected");
client.broadcast.emit("chat", name + ": " + data);
So if you want them printed in the same client window, you'll have to also client.emit
directly under them, to send the message to the client window who caused the actions.
Edit: This is from the docs: Broadcasting means sending a message to everyone else except for the socket that starts it.
Your server broadcasts chat
events, but your client is listening for messages
events only. (FIXED)
Let me know if you have any other issues.