I am trying to use socket io so I can dynamically update data on a site:
Edit: Updated Code
In app.js:
var express = require('express');
var app = express();
var routes = require('./routes/index');
app.use('/', routes);
var server = require('http').createServer(app);
var io = require('socket.io')(server);
io.on('connection', function(socket){
socket.emit('news', {hello: 'world'});
socket.on('my other event', function (data) {
console.log(data);
});
});
server.listen(app.get('port'), function(){
console.log('Express listening on port ' + app.get('port'));
});
In index.ejs:
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost:80');
socket.on('news', function(data) {
socket.emit('my other event', {my: 'data'});
});
</script>
The page loads correctly, however the socketio script does nothing. I have tried to make the code as simple as possible.
Express listening on port 80 outputs to console fine.
in www.
#!/usr/bin/env node
/**
* Module dependencies.
*/
var app = require('../app');
var debug = require('debug')('untitled:server');
var http = require('http');
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
/**
* Create HTTP server.
*/
var server = require('http').Server(app);
//var io = require('socket.io')(server);
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) {
var port = parseInt(val, 10);
if (isNaN(port)) {
// named pipe
return val;
}
if (port >= 0) {
// port number
return port;
}
return false;
}
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}
Not quite sure by what you mean as "socket script doesn't do anything" as you aren't really doing anything on the client side! From the code posted anyway.
EDIT:
This code works for me on the client and server.
server.js
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.set('view engine', 'jade');
app.set('views', './views');
app.get('/', function (req, res) {
res.render('index');
});
io.on('connection', function (socket) {
console.log('connected via server');
});
http.listen(3000, function () {
console.log('app listening on port 3000');
});
index.jade (you can use ejs or html)
html
head
script(src="/socket.io/socket.io.js")
script.
var socket = io.connect();
socket.on('connect', function() {
console.log('greetings from client');
});
body
h1 hello world
You can also try serving up the socket.io-client package yourself manually.
Check if app.get('port') works correctly and how do you serve the static site.
I tried to set it explicitly and works:
app.js
var express = require('express');
var app = express();
app.set('view engine', 'ejs');
app.set('views', './views');
app.get('/', function (req, res) {
res.render('index');
});
var server = require('http').createServer(app);
var io = require('socket.io')(server);
io.on('connection', function(socket){
socket.emit('news', {hello: 'world'});
socket.on('my other event', function (data) {
console.log(data);
});
});
server.listen(3100, function(){
console.log('Express listening on port ' + 3100);
});
index.ejs
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost:3100');
socket.on('news', function(data) {
socket.emit('my other event', {my: 'data'});
});
</script>
Or use <script src="http://localhost:3100/socket.io/socket.io.js"></script> if the static site is hosted in elsewhere.
Finally solved it:
Using socket.io in Express 4 and express-generator's /bin/www
I had to make some changes for express 4.0
Related
I have an expressjs generated app which is configured with socket io and I would like to implement nodejs clusters in it. The problem is that in Express 4.x the server listening configuration is in the bin/www file and no longer in app.js file.
Also my app is configured with socket io so I don't want to brake it too.
This is how it should be implemented in express apps according to this article:
app.js
// Include the cluster module
var cluster = require('cluster');
// Code to run if we're in the master process
if (cluster.isMaster) {
// Count the machine's CPUs
var cpuCount = require('os').cpus().length;
// Create a worker for each CPU
for (var i = 0; i < cpuCount; i += 1) {
cluster.fork();
}
// Listen for dying workers
cluster.on('exit', function (worker) {
// Replace the dead worker, we're not sentimental
console.log('Worker %d died :(', worker.id);
cluster.fork();
});
// Code to run if we're in a worker process
} else {
// Include Express
var express = require('express');
// Create a new Express application
var app = express();
// Add a basic route – index page
app.get('/', function (request, response) {
console.log('Request to worker %d', cluster.worker.id);
response.send('Hello from Worker ' + cluster.worker.id);
});
// Bind to a port
app.listen(3000);
console.log('Worker %d running!', cluster.worker.id);
}
And this is what I have:
app.js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var app = express();
var io = app.io = require('socket.io')();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
var players = {};
//socket io
io.on('connection', function(socket) {
socket.on('new player', function(data) {
var player = {
id: socket.id,
name: data.name,
color: data.color
}
players[socket.id] = player;
io.to(`${socket.id}`).emit('player info', player);
});
socket.on('chat', function(data) {
io.emit('message', {
player: players[data.id],
text: data.text
});
});
socket.on('disconnect', function() {
delete players[socket.id];
});
});
module.exports = app;
bin/www
#!/usr/bin/env node
/**
* Module dependencies.
*/
var app = require('../app');
var debug = require('debug')('elvin:server');
var http = require('http');
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '80');
app.set('port', port);
/**
* Create HTTP server.
*/
var server = http.createServer(app);
var io = app.io
io.attach(server);
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port, function(){
console.log('server listening on port ' + server.address().port);
});
server.on('error', onError);
server.on('listening', onListening);
/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) {
var port = parseInt(val, 10);
if (isNaN(port)) {
// named pipe
return val;
}
if (port >= 0) {
// port number
return port;
}
return false;
}
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}
What do I do? The module.exports = app; is what it is causing me troubles
I use my own boiler plate. I used socket, cluster and express together in it. Here is a link to it.
Desktop-CHAT-app
You can download it and make the changes over here and proceed. I've used many useful packages too.
Hope it helps!
I am reasonably new to node express and am trying to set up a simple server with middleware to handle routing.
The error I'm getting is TypeError: Router.use() requires a middleware function but got a Object
The error is because of the app.get('/', require(routes)); line. Does anyone know what I need to put here as a middleware function?
//server.js
http = require('http');
let port = process.env.PORT || 3000;
let host = '127.0.0.1';
var express = require('express');
var app = express();
var routes = './api/routes/positions';
app.use('/', require(routes));
http.createServer(app).listen(port);
console.log('Listening at http://' + host + ':' + port);
//#########################
//positions.js
const express = require('express');
var router = express.Router();
router.get('/', (err, req, res, next) => {
res.status(200).json({
message: "hello from server"
});
});
module.exports.router;
You are exporting the module in wrong way from positions.js file.
you need to write
module.exports = router
instead of,
module.exports.router
What you have written will bind a new key router to exports object, but haven't assigned any value to it and hence it goes back to default the empty object {}.
Now express was expecting a function but got object and hence the error. You can verify it by checking the require(routes) in server.js file.
Update (advice)
Please study this formatted version of your code.
const http = require('http');
const express = require('express');
const routes = require('./api/routes/positions');
const port = process.env.PORT || 3000;
const host = '127.0.0.1';
const app = express();
app.use('/', routes);
http.createServer(app).listen(port);
console.log('Listening at http://' + host + ':' + port);
If you want to read more project, you can read this boilerplate written by me. It's bit old, but may serve you well.
#!/usr/bin/env node
/**
* Module dependencies.
*/
var app = require('../app');
var debug = require('debug')('ag:server');
var http = require('http');
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '3002');
app.set('port', port);
/**
* Create HTTP server.
*/
var server = http.createServer(app);
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) {
var port = parseInt(val, 10);
if (isNaN(port)) {
// named pipe
return val;
}
if (port >= 0) {
// port number
return port;
}
return false;
}
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}
Try this one:
//server.js
let port = process.env.PORT || 3000;
let host = '127.0.0.1';
var express = require('express');
var app = express();
var routes = require('./api/routes/positions');
http.createServer(app).listen(port);
console.log('Listening at http://' + host + ':' + port);
//#########################
//positions.js
const express = require('express');
var router = express.Router();
router.use('/', routes);
app.use('/', routes);
router.get('/', (err, req, res, next) => {
res.status(200).json({
message: "hello from server"
});
});
module.exports = router;
I'm not getting an error but io.on('connection', function(socket){
console.log('a user connected', socket.client.id);
}); doesn't seem to work when I deployed my application in Linode.
But in the development it's working fine.
server.js ( socket io )
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var port = 8002;
io.on('connection', function (socket) {
console.log('a user connected', socket.client.id); // triggering in the development
});
http.listen(port, function () {
console.log('Express server listening on port ' + port);
console.log('env = ' + app.get('env') +
'\n__dirname = ' + __dirname +
'\nprocess.cwd = ' + process.cwd());
});
client html ( note: i change the localhost to my web app ip)
<script src="http://localhost:8002/socket.io/socket.io.js"></script>
and my application seem to be using the socket.io polling-xhr.js
I'm kind of new to this.
I don't know if this will fix your particular problem, but in order to set up socket.io on the same port that your application uses you can configure it this way:
const express = require('express');
const app = express();
const http = require('http');
const hostname = 'localhost';
const port = 80;
// the express app is registered with the server
const server = http.createServer(app);
// setup socket.io and register it with the server
const io = require('socket.io').listen(server);
// tell the application to listen on the port specified
server.listen(port, hostname, function (err) {
if (err) {
throw err;
}
console.log('server listening on: ', hostname, ':', port);
});
Now socket.io runs on the same port as your application.
I want to initialize my socket inside a route and according to documents I have to pass server instance to my socket. I have a separate server.js file like this:
var app = require('./app');
var http = require('http');
var port = '2002';
app.set('port', port);
var server = http.createServer(app);
server.listen(port, function(err){
if(err)
console.log(err);
else
console.log('Server listening on port : ' + port);
});
module.exports = server;
and my router:
var express = require('express');
var server = require('../server');
var router = express.Router();
var io = require('socket.io')(server);
router.get('/', function(req, res, next){
res.render('index');
});
router.post('/', function(req, res, next){
io.on('connection', function(socket){
socket.emit('server emit', { hello: 'server emit' });
socket.on('client emit', function (data) {
console.log("Server received : " + data);
});
});
});
module.exports = router;
and my client script:
var socket = io('http://localhost:2002');
socket.on('connect', function() {
socket.on('server emit', function(data) {
console.log('inside eventtt');
console.log(data);
});
});
But I face this error in my browser console:
socket.io-1.4.5.js:1 GET http://localhost:2002/socket.io/?EIO=3&transport=polling&t=LPajDxI
I think the problem is due to wrong initialization of my socket on the server side, but I don't know how to handle the problem.
I need debugging help in regards to my chat application. I followed instructions from an E-Book on Socket.IO but the application will not recognize any client to server/server to client interactions. No error is reported when I run my node application so I have to idea how to debug my code. The working application should be able to send client messages to the server to be displayed by all clients with a socket connection. My "www" file in "bin" runs the node server. My folder structure is as follows:
www file:
#!/usr/bin/env node
/**
* Module dependencies.
*/
var app = require('../app');
var debug = require('debug')('socketio:server');
var http = require('http');
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
/**
* Create HTTP server.
*/
var server = http.createServer(app);
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
require('../routes/socket.js').initialize(server);
/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) {
var port = parseInt(val, 10);
if (isNaN(port)) {
// named pipe
return val;
}
if (port >= 0) {
// port number
return port;
}
return false;
}
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}
app.js:
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
public/javascripts/chat.js:
var socket = io.connect('/');
socket.on('message', function (data) {
data = JSON.parse(data);
$('#messages').append('<div class="'+data.type+'">' + data.message + '</div>');
});
$(function(){
$('#send').click(function(){
var data = {
message: $('#message').val(),
type:'userMessage'
};
socket.send(JSON.stringify(data));
$('#message').val('');
});
});
routes/socket.js
var io = require('socket.io');
exports.initialize = function(server) {
io = io.listen(server);
io.sockets.on("connection", function(socket){
socket.send(JSON.stringify(
{type:'serverMessage',
message: 'Welcome to the most interesting chat room on earth!'}));
socket.on('message', function(message){
message= JSON.parse(message);
if(message.type == "userMessage"){
socket.broadcast.send(JSON.stringify(message));
message.type = "myMessage";
socket.send(JSON.stringify(message));
}
});
});
};
layout.jade
doctype html
html
block head
title= title
link(rel='stylesheet', href='/stylesheets/style.css')
script(type='text/javascript', src='http://code.jquery.com/jquery-1.11.0.min.js')
body
header#banner
h1 Awesome Chat
block content
footer hope you enjoy your stay here!
index.jade:
extends layout
block append head
script(type='text/javascript', src='/socket.io/socket.io.js')
script(type='text/javascript', src='/javascripts/chat.js')
block content
section#chatroom
div#messages
input#message(type='text', placeholder='Enter your message here')
input#send(type='button', value='Send')