socket.io not work on node.js server (with express) - node.js

I use express to generate my site(i.e. express mysite); I add socket.io support in my site. But when my socket.io client try to connect server, I found the server has kept receiving 'connection' event(.on('connection', function(socket)...) and client doesn't receive any message...
In my /bin/www
var app = require('../app');
var debug = require('debug')('mysite:server');
var http = require('http');
var https= require('https');
var fs = require('fs');
//Get port from environment and store in Express.
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
app.set('httpsport', 443);
//Create HTTP server.
var options = {
key: fs.readFileSync('.\file.pem'),
cert: fs.readFileSync('.\file.crt')
};
var server = http.createServer(app);
var httpsServer = https.createServer(options, app).listen(app.get('httpsport'));
//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) {
..........
}
//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);
}
//socket.io
var io = require('socket.io')(httpsServer);
io.on('connection', function(socket) {
//keep printing 'new connection' string in console
console.log('new connection');
//client doesn't receive this message
socket.emit('message', {'message': 'hello world'});
});
my client:
<html>
<head>
<script src="https://cdn.socket.io/socket.io-1.0.0.js"></script>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
</head>
<body>
<script>
var URL_SERVER = 'https://localhost:443';
var socket = io.connect(URL_SERVER);
socket.on('message', function(data) {
$('#message').text(data.message);
});
</script>
<div id="message">Message</div>
</body>
</html>
any suggestion?

You are referencing a very old version of socket.io (1.0.0) in your client. You don't specify which version of socket.io you're using on the server, but ideally the client and server should match.
socket.io will serve its matching client script at the /socket.io/socket.io.js path of your server, or you can use a newer version from a CDN.
https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.7.4/socket.io.js
https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js
Your code runs as expected for me with both the latest version from the 1.x branch (1.7.4) and the latest version from the 2.x branch (2.0.4)

Related

Chat application using socket.io not connecting when deploying on production server

I am trying to implement chat application using nodejs and socket.io. The application works on localhost. But when I deploy same on my production server then socket.io can't make any connection.
Code for server.js
var express = require('express');
var app = express();
var socket = require('socket.io');
var chat_controller = require('./controllers/ChatController.js');
var user_controller = require('./controllers/UserController.js');
var Group_controller = require('./controllers/GroupChatController.js');
app.get('/search', function (req, res) {
user_controller.get(req, res);
});
app.get('/groupSearch', function (req, res) {
user_controller.get(req, res);
});
var server = app.listen(3600, function () {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
});
var io = socket(server);
io.on('connection', (socket) => {
console.log('made socket connection', socket.id);
socket.broadcast.emit('userconnected');
chat_controller.respond(io, socket);
Group_controller.respond(io, socket);
user_controller.respond(io, socket);
});
io.on('disconnect', function () {
console.log('made socket disconnect', socket.id);
});
Code for client.js
var socket = io.connect('https://www.mywebsite.com', {
path: '/apichat'
});
/* Other events related to socket. */
As my server uses SSL I can't used IP:PORT directly so I am using ProxyPass as
ProxyPass /apichat http://127.0.0.1:3600
After all this still socket connection is not established between server and client.
Error shown in browser console is:
POST https://www.mywebsite.com/apichat/?EIO=3&transport=polling&t=MUc-TJK 404 (Not Found)
And in browser Network tab it shows:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Cannot POST /</pre>
</body>
</html>
I have checked many other questions posted here and other sites but no question address this issue.
Please Help.
The issue you are encountering is probably due to ssl enabled on your website.
You need to pass ssl related files in your app.js file. Sample code for this is as follow:
var fs = require('fs');
var options = {
key: fs.readFileSync('PATH_TO_SSL_KEYS.key'),
cert: fs.readFileSync('PATH_TO_SSL_CERTS.crt'),
ca: fs.readFileSync('PATH_TO_SSL.pem')
};
var app = require('https').createServer(options, handler), io = require('socket.io').listen(app);
io.set('transports', [
'websocket',
'flashsocket',
'htmlfile',
'xhr-polling',
'jsonp-polling',
'polling'
]);
function handler(req, res) {
res.writeHead(200);
res.end("welcome sir!");
}
var chat_controller = require('./controllers/ChatController.js');
var user_controller = require('./controllers/UserController.js');
io.sockets.on('connection', function (socket) {
socket.broadcast.emit('userconnected');
chat_controller.respond(io, socket);
user_controller.respond(io, socket);
socket.on('message', function (data) {
socket.broadcast.emit('message', data);
});
});
io.on('disconnect', function (socket) {
console.log('made socket disconnect', socket.id);
});
app.listen(3300);
Try editing your application file as per above mentioned sample code and then try to use it. If you can't get path to ssl related file, then you need to contact either your system administrator or the hosting provider.
I hope it helped.

Node.Js MQTT Broker

I am having the following code in node.js.
It connects fine to the broker I have set on my personal website/server, and it is able to send and listen to the events from the server.js.
My problem is that it does not listen to other events that are sent to the broker from other devices. How can I make sure that the code below will manage to listen to all events from the broker?
Thanks
var mqtt = require('mqtt')
var MQTT_TOPIC = "homeGet/light";
var MQTT_ADDR = "mqtt://broker.example.org:80";
var MQTT_PORT = 80;
var client = mqtt.connect(MQTT_ADDR,{clientId: "webClient", keeplive: 1, clean: false, debug:true});
var express = require('express');
var socket = require('socket.io');
//store the express functions to var app
var app = express();
//Create a server on localhost:5000
var server = app.listen(process.env.PORT || 5000);
//var server = app.listen((process.env.PORT || 3000, function(){
//console.log("Express server listening on port %d in %s mode", this.address().port, app.settings.env);
//});
//host content as static on public
app.use(express.static('public'));
console.log("Node is running on port 5000...");
//MQTT
client.on('connect', function () {
client.subscribe(MQTT_TOPIC, { qos: 2 });
client.publish(MQTT_TOPIC, '1000');
});
client.on('message', function (topic, message) {
// message is Buffer
console.log(message.toString());
client.end();
});
client.on('error', function(){
console.log("ERROR")
client.end()
})
client.on('offline', function() {
console.log("offline");
});
client.on('reconnect', function() {
console.log("reconnect");
});
You have client.end() in your client.on('message',function(message){...}) callback.
This will disconnect the client as soon as it receives it's first message.
Assuming you copied this from the example in the README.md for the mqtt package on npm. That example is specifically set up to receive only one message.

Websocket connection in Node.js closes on sending

I tried many different npm web socket libraries (WebSocket, ws, express-ws and more), and in EVERYONE of them I have the same problem. When I try to send a websocket message, the connection closes.
I have no problem receiving messeges, only sending.
Here is one simple example of one test with express and ws libraries:
Node.JS side:
var server = require('http').createServer()
, url = require('url')
, WebSocketServer = require('ws').Server
, wss = new WebSocketServer({ server: server })
, express = require('express')
, app = express()
, port = 8080
, fs = require('fs');
app.use(function (req, res) {
var index = fs.readFileSync('./interface/index.html');
res.end(index);
});
wss.on('connection', function connection(ws) {
var location = url.parse(ws.upgradeReq.url, true);
console.log('open ws');
ws.on('message', function incoming(message) {
console.log('received: %s', message);
ws.send('test back');
});
ws.on('close', function () {
console.log('ws connection closed.');
})
});
server.on('request', app);
server.listen(port, function () { console.log('Listening on ' + server.address().port) });
and the browser side ("./interface/index.html"):
window.WebSocket = window.WebSocket || window.MozWebSocket;
var port = 8080;
var ip = window.location.hostname;
var connection;
connection = new WebSocket('ws://' + ip + ':' + port);
connection.onopen = function () {
// connection is opened and ready to use
console.log('Web socket connection with', ip + ':' + port);
//sendQueue(msgQueue);
};
connection.onerror = function (error) {
// an error occurred when sending/receiving data
console.log('Web socket erorr with', ip + ':' + port + ':', error);
};
connection.onmessage = function (message) {
// try to decode json (I assume that each message from server is json)
console.log("Received ws");
// handle incoming message
};
connection.onclose = function (){
console.log("Web socket connection lost.");
};
function sendws() {
connection.send("test");
console.log("sent ws");
return false;
}
<head>
<meta charset="utf-8">
<title>Simple Web Socket test</title>
<!--<meta name="description" content="Simple Web Socket">-->
<meta name="author" content="Binoman">
<link rel="stylesheet" href="css/styles.css?v=1.0">
<!--[if lt IE 9]>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script>
<![endif]-->
</head>
<body>
<button type="button" name="button" onclick="sendws()">Send</button>
</body>
I have no idea why this is happening. I updated Node.js to 6.7.
Running on windows 10.
I appreciate the help!
Thanks!
I discovered it was my antivirus's web protection that blocked the connection. I made an exception for my localhost address and it working perfectly now.

Node js, Call WebSocket server from http server

I have a node js ( supported by express js ) http application. So I had a server.js file as follows(not there complete code).
var app = require('./app/app');
var server = http.createServer(app);
server.listen(port, host);
server.on('error', onError);
server.on('listening', onListening);
I later added websocket server to there. So it is like this now.
// app server
var app = require('./app/app');
var server = http.createServer(app);
server.listen(port, host);
server.on('error', onError);
server.on('listening', onListening);
/**
* websocker Server
*/
var WebSocket = require('ws');
var wsServer = http.createServer();
var url = require('url');
var WebSocketServer = require('ws').Server;
var wss = new WebSocketServer({ server: wsServer });
var express = require('express');
var wsApp = express();
var port = 1337;
wsApp.use(function (req, res) {
res.send({ msg: 'hello' });
});
wss.on('connection', function connection(ws) {
console.log((new Date()) + ' Connection from origin ');
ws.on('message', function incoming(message) {
console.log('received: %s', message);
var json = JSON.stringify({ type:'message', data: {hello : 'hello'} });
ws.send(json);
});
var json = JSON.stringify({ type:'message', data: {hello : 'hello'} });
ws.send(json);
});
wsServer.on('request', wsApp);
wsServer.listen(port, function () { console.log('Ws server Listening on ' + wsServer.address().port); });
Now these two are working happily. What I want is on a POST call to the http server, I want to trigger the web socket server to broadcast something to all clients. My problem is How I can trigger websocket server from http server?
Routes of http server is defined in app.js file. from there how can I call websocker server function?
If you encapsulate your ws functionality in one single javascript file (e.g: websocket.js) you could export your websocket object as a module.
module.exports = wss;
and then require it in your http controller
var wss = require(websocket.js)
In this case it should be easy to use wss.send({...}) wherever you like.
This peace of code is working to me:
//websocket.js
'use strict';
var io = require('socket.io');
var callme;
function Websocket(server) {
var server = io(server);
server.on('connection', function(socket){
console.log('Do something here');
});
callme = function (val) {
//you my choose a specific cliente if you want, read the socket.io doc
server.emit('I may emit it ' + val);
console.log("Called " + val);
return 'Somebody got it';
}
}
Websocket.route = function(req, res, next) {
if(typeof callme == 'function'){
res.send(callme(req.param('t')));
}else{
res.send('Websocket server is not running');
}
};
module.exports = Websocket;
On the express app definition, I put
var Websocket = require('./websocket');
app.use('/blablabla', Websocket.route);
Then, on the server js file, which run the application, I put
var server = http.createServer(app);
var s = new Websocket(server);
This last line works like the tradicional io(server); would work.
After that, when you request the address /blablabla the route will execute your websocket method.
My solution is not in production yet, let me know if somebody got an error.

Create WebSockets between a TCP server and HTTP server in node.js

I have created a TCP server using Node.js which listens to clients connections.
I need to transmit data from TCP server to HTTP server again in Node.js possibly through a Websocket (socket.io).
However, I do not know how to create such connection such that TCP server is able to push data to HTTP server through Websocket.
Many Thanks.
I was trying lot of things to get this work. Most of the time I was relying on socket.io to get this working, but it was just not working with TCP.
However, net.Socket suffices the purpose.
Here is the working example of it.
TCP Server
var net = require('net');
var HOST = 'localhost';
var PORT = 4040;
var server = net.createServer();
server.listen(PORT, HOST);
server.on('connection', function(sock) {
console.log('CONNECTED: ' + sock.remoteAddress +':'+ sock.remotePort);
sock.write("TCP sending message : 1");
console.log('Server listening on ' + server.address().address +':'+
server.address().port);
}).listen(PORT, HOST);
HTTP Server
var http = require('http').createServer(httpHandler),
fs = require("fs"),
wsock = require('socket.io').listen(http),
tcpsock = require('net');
var http_port = 8888;
var tcp_HOST = 'localhost';
var tcp_PORT = 4040;
/**
* http server
*/
function httpHandler (req, res) {
fs.readFile(__dirname + '/index.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
http.listen(http_port);
console.info("HTTP server listening on " + http_port);
wsock.sockets.on('connection', function (socket) {
var tcpClient = new tcpsock.Socket();
tcpClient.setEncoding("ascii");
tcpClient.setKeepAlive(true);
tcpClient.connect(tcp_PORT, tcp_HOST, function() {
console.info('CONNECTED TO : ' + tcp_HOST + ':' + tcp_PORT);
tcpClient.on('data', function(data) {
console.log('DATA: ' + data);
socket.emit("httpServer", data);
});
tcpClient.on('end', function(data) {
console.log('END DATA : ' + data);
});
});
socket.on('tcp-manager', function(message) {
console.log('"tcp" : ' + message);
return;
});
socket.emit("httpServer", "Initial Data");
});
Browser Client
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.on('httpServer', function (data) {
console.log(data);
document.write(data + "\r\n");
socket.emit('tcp', "For TCP");
});
</script>
This way, there is a socket opened between HTTP server and TCP server in Node.js.
If you need to communicate server-server than websockets is probably not a best choice. Try one of RPC libraries, or just use HTTP or your own protocol.
You can use either socket.io or ws (only WebSocket) on Node.js as client (not only in browser)
var io = require('socket.io-client');
var socket = io.connect('http://IP address of Websocket server');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});

Resources