Socket.io getting disconnected unexpectedly - node.js

<body>
<ul id="messages"></ul>
<form action="">
<input id="m" autocomplete="off" /><button onclick="message()">Send</button>
</form>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
var message = function(){
var msg = document.getElementById("m").value;
if(msg !== ""){
alert(msg);
socket.emit('chat message',msg);
}
document.getElementById("m").value="";
}
socket.on('display',function(value){
console.log(value);
document.getElementById("messages").innerHTML += "<li>"+value+"</li>";
})
</script>
This is my index.html page to design a group chat using socket.io
var express = require('express');
var app = express();
var http = require('http').createServer(app);
var io = require('socket.io')(http);
app.get('/', function(request, response) {
response.sendFile(__dirname + '/index.html');
});
io.on('connection',function(socket){
console.log('a user connected');
socket.on('chat message',function(msg){
console.log('message: '+msg);
io.emit('display',msg);
});
socket.on('disconnect',function(){
console.log('user disconnected')
})
});
http.listen(3000, function() {
console.log("listening on 3000");
});
This is my index.js file. The user is getting disconnected each time a message is sent. Any suggestions why this happened
Thanks in advance

Add message(event) to your form:
<form action="">
<input id="m" autocomplete="off" /><button onclick="message(event)">Send</button>
</form>
and change your message function to:
var message = function(event){
event.preventDefault();
var msg = document.getElementById("m").value;
if(msg !== ""){
alert(msg);
socket.emit('chat message',msg);
}
document.getElementById("m").value="";
}
The default html method when you submit a form is GET. When express receives GET it resends index.html to the browser and the page refreshes. We can change it with event.preventDefault(). It should work now.

You shouldn't do:
io.emit
You should do:
socket.emit

Related

After server starts running ,why do sockets keep on getting connected infinitely in nodejs?

I am new to nodejs,how come sockets get connected automatically till I stop the server.It should connect one socket at a time?
After I open html page in browser sockets keep on getting connected on their own!
It is expected that only one socket should be connected after server starts running.
How can I connect one socket at a time?
server.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.get('/',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);
socket.on('disconnect',function(data){
connections.splice(connections.indexOf(socket), 1);
console.log('Disconnected %s sockets connected',connections.length);
});
socket.on('send message',function(data){
io.sockets.emit('new message',{msg : data});
});
});
index.html
<!doctype html>
<html>
<head>
<title>Chat</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap /3.3.6/css/bootstrap.min.css">
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script src="/socket.io/socket.io.js /"></script>
<style>
body{
margin-top:30px;}
</style>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-4">
<div class="well">
<h3> Online users </h3>
<ul class="list-group" id="users"> </ul>
</div>
</div>
<div class="col-md-8">
<div class="chat" id="chat">
<form id="messageForm">
<div class="form-group">
<label>Enter Message</label>
<textarea class="form-control" id="message"></textarea>
</br>
<input type="submit" class="btn btn-primary" value="Send message"/>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<script>
$(function(){
var socket = io.connect();
var $messageForm = $('#messageForm');
var $message = $('#message');
var $chat = $('#chat');
$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">'+data.msg+'</div>');
});
});
</script>
</body>
</html>
Here is a bit more complete solution with some notes for you.
Socket.io has long had some snafus with multiple connections. This can and will happen for things such as intermittent connectivity between client and server to past bugs.
You may want to also checkout ws on npmjs.com see > https://www.npmjs.com/package/ws
For some reference as to how templating works in NodeJS/Express see > https://expressjs.com/en/advanced/developing-template-engines.html
Hopefully this will put you in the right direction...
const express = require('express');
const app = express();
const server = require('http').createServer(app);
const io = require('socket.io').listen(server);
const cons = require('consolidate'); // enables using any template engine.
server.maxConnections = 5; // you can limit connections to server if you wish.
const connections = [];
// Handle your template & engine.
app.engine('html', cons.swig); // where "swig" is the template lang u want to use.
app.set('views', 'your/path/to/views'); // where your views folder lives.
app.set('view engine', 'html'); // the extension of the templates without "."
app.get('/', function (req, res) {
res.render('index', { /* your locals here */ });
});
io.sockets.on('connection', function (socket) {
connections.push(socket);
console.log('Connected: %s sockets connected', connections.length);
socket.on('disconnect', function (data) {
connections.splice(connections.indexOf(socket), 1);
console.log('Disconnected %s sockets connected', connections.length);
});
socket.on('send message', function (data) { // wouldn't use event names with spaces
io.sockets.emit('new message', { // you could do something like 'message:new' & 'message:received' for the above.
msg: data
});
});
});
server.listen(process.env.port || 3000, () => {
const address = server.address();
const host = address.address;
const port = address.port;
console.log(`Server listening at ${host}:${port}.`);
});
// NOTE: Below handles ctrl-c for Win //
// This will allow for graceful shutdown of connections.
if (process.platform === "win32") { // this is required for handling on windows.
var rl = require("readline").createInterface({
input: process.stdin,
output: process.stdout
});
rl.on("SIGINT", function () {
process.emit("SIGINT");
});
}
process.on("SIGINT", function () {
connections.forEach((socket) => {
// destroy your sockets here!
});
process.exit();
});

HTML button communicating with Node server + Socket.io

When a user clicks an html button (#new) I want to store their socket.id into an array (userQueue) on my node server but I'm having trouble figuring out how to do this. Do I need to set up a post request or is there a way through socket.io?
App.js (Server):
// App setup
var express = require('express'),
socket = require('socket.io'),
app = express(),
bodyParser = require("body-parser");
var server = app.listen(3000, function() {
console.log('listening to requests on port 3000');
});
var io = socket(server);
app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static('public'));
// Room Logic
var userQueue = [];
io.on('connection', function(socket) {
console.log('made socket connection', socket.id);
socket.on('chat', function(data) {
io.sockets.emit('chat', data);
});
socket.on('typing', function(data) {
socket.broadcast.emit('typing', data);
});
});
Chat.js (client side):
// Make connection
var socket = io.connect('http://localhost:3000');
// Query DOM
var message = document.getElementById('message');
handle = document.getElementById('handle'),
btn = document.getElementById('send'),
btnNew = document.getElementById('new'),
output = document.getElementById('output'),
feedback = document.getElementById('feedback');
// Emit events
btn.addEventListener('click', function(){
socket.emit('chat', {
message: message.value,
handle: handle.value
});
});
message.addEventListener('keypress', function() {
socket.emit('typing', handle.value);
});
// Listen for events
socket.on('chat', function(data) {
feedback.innerHTML = ""
output.innerHTML += '<p><strong>' + data.handle + ':</strong>' + data.message + '</p>'
});
// Emit 'is typing'
socket.on('typing', function(data) {
feedback.innerHTML = '<p><em>' + data + ' is typing a message...</em></p>'
});
Index.html:
<!DOCTYPE html>
<html>
<head>
<title>WebSockets 101</title>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script>
<link rel="stylesheet" type="text/css" href="/styles.css">
</head>
<body>
<div id="mario chat">
<div id="chat-window">
<div id="output"></div>
<div id="feedback"></div>
</div>
<input id="handle" type="text" placeholder="Handle">
<input id="message" type="text" placeholder="Message">
<button id="send">Send</button>
<button id="new">New</button>
</div>
<script type="text/javascript" src="/chat.js"></script>
</body>
</html>
I believe that a post request will probably work as well, but if you want to simply work with socket.io you can consider doing something similar to your chat event by adding this in your chat.js:
btnNew.addEventListener('click', function() {
socket.emit('new user', socket.id);
});
And on the server side, app.js:
socket.on('new user', function(id) {
userQueue.push(id);
});
And it should be stored in the array. Hope this helps!

Append a div with an array in Node.js

I am creating a chat where there will be a div that displays the users that have connected to the server. The user's name is being taken from a prompt. I have managed to push each connected user to the array but can't figure out how to display that array. At the moment it only appends the div with the name of the individual user but I want them all to be displayed.
<body>
<div id="chatlog" class="col-sm-9">
<ul id="messages"></ul>
</div>
<div id="online" class="col-sm-3">
<div id="username"></div>
</div>
<form class="col-sm-12" action="">
<input id="type" type="text" />
<input type="submit" id="submit" />
</form>
<script>
var socket = io();
var user = prompt("What's your name?");
$('form').submit(function() {
socket.emit('chat message', $('#type').val());
$('#type').val('');
return false;
});
socket.on('chat message', function(msg) {
$('#messages').append($('<li>').text(msg));
});
socket.emit("join", user);
socket.on("join", function(user) {
$("#username").append($("<p>").text(user));
})
</script>
</body>
server.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var express = require("express");
var port = 3000;
var onlineUsers = [];
console.log(onlineUsers);
app.use(express.static(__dirname + '/'));
app.get('/', function(req, res) {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket) {
console.log('a user connected');
socket.on("join", function(user) {
socket.emit("join", user);
onlineUsers.push(user);
console.log(onlineUsers);
});
socket.on('chat message', function(msg) {
console.log('message: ' + msg);
io.emit('chat message', msg);
});
socket.on('disconnect', function() {
console.log('user disconnected');
});
});
http.listen(port, function() {
console.log('listening on *:' + port);
});
I am also open to suggestions how to do this another way but node.js is very new to me and think this might be the easiest way.
Send the array of users back to the clients when a user joins. This way all clients will have a updated user list every time a user joins. Below is a suggestion on how you could implement this
server:
socket.on("join", function(user) {
onlineUsers.push(user);
io.emit("user list", onlineUsers);
});
client:
socket.emit("join", user);
socket.on('user list', function(onlineUsers) {
$("#username").empty();
for(var i=0;i<onlineUsers.length;i++){
$("#username").append($("<p>").text(onlineUsers[i]));
}
});

socket.io and node js: chat does not display on screen

I was giving a try to socket.io by creating a live chat, and the page refreshes itself when the message is submitted, here is the markup and the client side JS (index.html):
<body>
<h1>Open chat</h1>
<form id="send_message">
<div class="chat">
</div>
<hr />
<input size="28" type="text" id="message" />
<input type="submit" value="send" />
</form>
<script src="http://code.jquery.com/jquery-latest-min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script>
JQuery(function($){
var socket = io.connect();
var $message_form = $('#send_message');
var $message_box = $('#message');
var $chat = $('#chat');
$message_form.submit(function(e){
e.preventDefault();
socket.emit('send message', $message_box.val());
$message_box.val('');
})
});
socket.on('new message', function(data){
$chat.append(data+'<br />');
});
</script>
</body>
and here is the server side js (app.js):
var express = require('express'),
app = express(),
server = require('http').createServer(app),
io = require('socket.io').listen(server);
server.listen(3000);
app.get('/',function(req, res){
res.sendfile(__dirname + '/index.html');
});
io.sockets.on('connection',function(socket){
socket.on('send message', function(data){
io.sockets.emit('new message',data);
});
});
I know you guys won't need this but this is package.json:
{
"name":"test_chat_application",
"version":"0.0.1",
"private":"true",
"dependencies":{
"socket.io":"1.4.8",
"express":"4.14.0"
}
}
basically i think the problem is the page refresh!
please help..
You have to ditch the form, update some of the stuff (like var socket = io() instead of var socket = io.connect() and stuff) and handle your send button with onclick events instead of form submissions. That way you won't refresh.
Anyway, the updated server.js:
var express = require('express'),
app = express(),
server = require('http').createServer(app),
io = require('socket.io').listen(server);
server.listen(3000);
app.use(express.static('./'));
app.get('/',function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.on('connection',function(socket){
console.log('SOMEONE CONNECTED:', socket.id);
socket.on('send', function(data){
console.log(data);
io.sockets.emit('new', data);
});
});
index.html
<body>
<h1>Open chat</h1>
<div class="chat">
<ul id="messages">
</ul>
</div>
<hr />
<input size="28" type="text" id="message" />
<input type="button" onclick="send()" value="send" />
<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
<script>
var socket = io();
function send(){
var message = document.getElementById("message").value;
socket.emit("send", { "message" : message });
document.getElementById("message").value = "";
}
socket.on("new", function(data){
console.log("NEW MESSAGE : ", data);
var chatMessage = document.createElement("li");
chatMessage.innerHTML = data.message;
document.getElementById("messages").appendChild(chatMessage)
});
</script>
Try this and let me know if it works
I think you should add return false to prevent the form from being 'really' submitted (and thus refreshing the page). Submit event is not bubbling I think, so e.preventDefault doesn't work in this case.
$message_form.submit(function(e){
e.preventDefault();
socket.emit('send message', $message_box.val());
$message_box.val('');
return false;
})
<div class="chat"></div> <!-- this is class -->
// But you are using
var $chat = $('#chat');
Also move chat container outside of form#send_message and use document.ready
this should work well
<div class="chat"></div>
<hr />
<form id="send_message">
<input size="28" type="text" id="message" />
<input type="submit" value="send" />
</form>
<script>
$(document).ready(function() {
var socket = io.connect();
var $message_form = $('#send_message');
var $message_box = $('#message');
var $chat = $('#chat');
$message_form.submit(function(e){
e.preventDefault();
socket.emit('send message', $message_box.val());
$message_box.val('');
});
socket.on('new message', function(data){
$chat.append(data+'<br />');
});
});
</script>
better way
As you are using socket (which kind of ajax) - you loose all benefits of form element, so simply don't use it
<div class="chat"></div>
<hr />
<input size="28" type="text" id="message"/>
<button id="send_message">send</button>
<script>
$(document).ready(function() {
var socket = io.connect();
var $message_form = $('#send_message');
var $message_box = $('#message');
var $chat = $('#chat');
$message_form.click(function(){
socket.emit('send message', $message_box.val());
$message_box.val('');
});
socket.on('new message', function(data){
$chat.append(data+'<br />');
});
});
</script>

Basic chat application with socket/node/express - Nothing gets printed out

I am just trying to do a very basic chat application with socket.io and node. I am unable to see anything get printed out to my screen, and cannot find any errors. Appreciate the help!
Thanks.
app.js
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io').listen(server);
server.listen(3000);
console.log('Server running...');
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.sockets.on('connection', function(socket){
socket.on('send-message', function(data){
io.sockets.emit('new message', data);
});
});
index.html
<html>
<title>Chat Test</title>
<style> #chat{
height: 500px;
}
</style>
<head>
<body>
<div id = "chat"></div>
<form id = "send-message">
<input size = "35" id = "message"></input>
<input type = "submit"></input>
</form>
<script src ="https://code.jquery.com/jquery-latest.min.js"></script>
<script src ="/socket.io/socket.io.js"></script>
<script>
JQuery(function($){
var socket = io.connect();
var $messageForm = $('#send-message');
var $messageBox = $('#message');
var $chat = $('#chat');
$messageForm.submit(function(e){
e.preventDefault();
socket.emit('send-message', $messageBox.val());
$messageBox.val('');
});
socket.on('new message', function(data){
$chat.append(data + "<br/>");
});
});
</script>
</body>
</head>
</html>
When using jQuery, you must spell it jQuery, not JQuery or you could just use the built-in alias $.
This should have shown an error in the debug console of the browser which is something you should learn to look for to see your own errors.
jQuery(function($){
var socket = io.connect();
var $messageForm = $('#send-message');
var $messageBox = $('#message');
var $chat = $('#chat');
$messageForm.submit(function(e){
e.preventDefault();
socket.emit('send-message', $messageBox.val());
$messageBox.val('');
});
socket.on('new message', function(data){
$chat.append(data + "<br/>");
});
});
After fixing this and then running your code and accessing http://localhost:3000, your app works just fine for me. Anything submitted in the form is broadcast to all connected clients.

Resources