Websocket connection in Node.js closes on sending - node.js

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.

Related

Node SocketIo - Client not emitting?

I'm having issues with Node SocketIo client not emitting data. So when the client connects in the index.html does log the "Connected This Is A Test", however it does not socket.emit('cool'), no errors nor does it seem to log on server.js. I'm not sure why its not emitting or the server isnt listening.
Server.js
const path = require('path');
const http = require('http');
const express = require('express');
const socketio = require('socket.io');
const app = express();
const server = http.createServer(app);
const io = socketio(server);
const PORT = 3002;
app.use(express.static(path.join(__dirname, 'public')));
// run when client connects
io.on('connection', () => {
console.log('New WS connection...');
io.emit('connection', 'This Is A Test');
});
io.on('cool', (msg) => {
console.log(msg);
});
server.listen(PORT, () => console.log(`server running on port ${PORT}`));
index.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title></title>
</head>
<body>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://' + document.domain + ':' + location.port);
socket.on('connection', function(data){
console.log("connected", data);
socket.emit('cool', 'MSG');
});
</script>
</body>
</html>
On your server, you need to be listening for the cool message on a specific connected socket, not on the io object. The io object does not have specific socket messages other than announcing a newly connected socket. To listen for messages from a specific socket, you need a listener on the connected socket itself. The usual place to add that listener is in the connection event where you are presented with the newly connected socket object.
So change this:
// run when client connects
io.on('connection', () => {
console.log('New WS connection...');
io.emit('connection', 'This Is A Test');
});
io.on('cool', (msg) => {
console.log(msg);
});
to this:
// run when client connects
io.on('connection', (socket) => {
console.log('New WS connection...');
// send a test event back to the socket that just connected
socket.emit('test', 'This Is A Test');
// listen for the cool message on this new socket
socket.on('cool', (msg) => {
console.log(msg);
});
});
Also, you really should not be emitting event names used by the system like connection. That's why I changed the event name to test so it won't conflict with names that socket.io itself is using.

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.

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

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)

Communicating TCP with HTTP in Socket.io getting TypeError: Cannot read property 'emit' of undefined

Trying to communicate TCP server with HTTP server
My TCP port is 4040 and HTTP port is 3000
I am working on passing data received on TCP server to HTTP server
Data received on TCP port is showing on console window and I am trying to pass this data to HTTP by storing data in global var so that I can display it on the webpage.
Thanks :)
server code:
enter code here var http = require('http').createServer(httpHandler);
var net = require('net');
var app = require('express')(); <!-- These are mandatory variables -->
var http = require('http').Server(app);
var io = require('socket.io')(http);
var sockets = [];
var HOST = 'localhost';
var PORT = 4040;
global.MYVAR = "Hello world";
global.MYVAR2 = "Hello world";
var server = net.createServer();
server.listen(PORT, HOST);
// Keep track of the chat clients
var clients = [];
/**
* 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);
});
}
app.get('/', function(req, res){ <!-- This sends the html file -->
//send the index.html file for all requests
res.sendFile(__dirname + '/index.html');
});
http.listen(3000, function(){ <!-- Tells the HTTP server which port to use -->
console.log('listening for HTTP on *:3000'); <!-- Outputs text to the console -->
console.log('listening for TCP on port ' + PORT);
});
<!-- everything below this line is actual commands for the actual app -->
io.on('connection', function(socket) // Opens the socket
{
socket.on('checkbox1', function(msg){ // Creates an event
console.log(msg); // displays the message in the console
MYVAR = msg; // Sets the global variable to be the contents of the message recieved
for (var i = 0; i < sockets.length; i++) {
if(sockets[i]) {
sockets[i].write(MYVAR, 'utf-8');
}
}
});
});
server.on('connection', function(socket){ // Opens the socket for the TCP connection
sockets.push(socket);
socket.write(MYVAR, 'utf-8');
// Handle incoming messages from clients.
socket.on('data', function (data) {
broadcast(socket.name + "> " + data, socket);
});
// Send a message to all clients
function broadcast(message, sender) {
MYVAR2 = message;
console.log(MYVAR2);
socket.broadcast.emit('updateHeader',MYVAR2); // GETTING ERROR HERE
}
}).listen(PORT, HOST);
index.html code:
<!doctype html>
<html>
<head>
<title>Socket IO Test</title>
</head>
<body>
<h1 id="h1">Hello World</h1>
<form action="">
<input type='checkbox' onclick='checkbox1(this);'>Checkbox1</label>
</form>
<script src="/socket.io/socket.io.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
var socket = io();
var number = 0;
$(document).ready(function(){
socket.on('updateHeader',function(data){
console.log('updateHeader called');
document.getElementById('h1').innerHTML = data;
});
});
function checkbox1(cb) {
socket.emit('checkbox1', 'checkbox 1 = ' + cb.checked);
return false;
}
</script>
The problem is you're trying to use socket.io broadcast in a net.Socket which of course doesn't have that property.
server.on('connection', function(socket){ /* ... */ }
When a new TCP stream is established. socket is an object of type
net.Socket. Usually users will not want to access this event. In
particular, the socket will not emit 'readable' events because of how
the protocol parser attaches to the socket. The socket can also be
accessed at request.connection.
I don't know exactly what you're trying to achieve, but you can use io.emit if you want to send message to all clients.
function broadcast(message, sender) {
MYVAR2 = message;
//This will emit 'updateHeader' to all socket.io connected sockets
io.emit('updateHeader', MYVAR2);
//The 'socket' you were using here was a net.Socket not a socket.io one.
}
function broadcast(message, sender) {
MYVAR2 = message;
console.log(MYVAR2);
sender.broadcast.emit('updateHeader',MYVAR2); //Replace socket by sender here
}

nodejs websocket detect disconnected socket

I have a nodejs websocket server and I have the following problem.
When my clients connect to the server and terminate gracefully the onclose method is called on those sockets and I perform clean up operations on the closed socket.
When the client disconnects due to network, the onclose method is not called. Is there any timeout to be set so onclose is called automatically after a timeout?
I am using ws package for the websocket server in nodejs
default ws implementation doesn't have a callback for network disconnects from client side
You can find a keepAlive implementation here
Well I'll try to answer your question with two examples. Try to analyze both of them and learn how they work. They are both tested and working.
1- Websocket:
Server:
var WebSocketServer = require('websocket').server;
var http = require('http');
var server = http.createServer(function(request, response) {
console.log((new Date()) + ' Received request for ' + request.url);
response.writeHead(404);
response.end();
});
server.listen(3000, function() {
console.log((new Date()) + ' Server is listening on port 3000');
});
wsServer = new WebSocketServer({
httpServer: server,
autoAcceptConnections: false
});
function originIsAllowed(origin) {
return true;
}
wsServer.on('request', function(request) {
if (!originIsAllowed(request.origin)) {
request.reject();
console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
return;
}
var connection = request.accept('echo-protocol', request.origin);
console.log((new Date()) + ' Connection accepted.');
connection.on('message', function(message) {
if (message.type === 'utf8') {
console.log('Received Message: ' + message.utf8Data);
connection.sendUTF(message.utf8Data);
}
else if (message.type === 'binary') {
console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');
connection.sendBytes(message.binaryData);
}
});
connection.on('close', function(reasonCode, description) {
console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
});
});
Client:
<!DOCTYPE html>
<html>
<head>
<title>Web socket Experiment</title>
<script type="text/javascript">
function callWebSocket() {
var socket = new WebSocket("ws://localhost:3000", 'echo-protocol');
socket.onopen = function () {
alert("Hello, Connected To WS server");
};
socket.onmessage = function (e) {
alert("The message received is : " + e.data);
};
socket.onerror = function (e) {
alert("An error occured while connecting... " + e.data);
};
socket.onclose = function () {
alert("hello.. The coonection has been clsoed");
};
}
</script>
</head>
<body>
<input type="button" value="Open Connecton" onclick="callWebSocket()" />
</body>
</html>
2- Socket.io:
Server:
var http = require('http');
var app = require('express')();
var httpServer = http.createServer(app)
var io = require('socket.io')(httpServer);
app.get('/', function(req, res) {
res.sendfile(__dirname + '/index.html');
});
io.on('connection', function(socket) {
socket.emit('news', {
hello: 'world'
});
socket.on('my other event', function(data) {
console.log(data);
});
socket.on('disconnect', function(data) {
console.log('disconnect!');
});
});
httpServer.listen(3000);
Client:
<html>
<head>
<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
<script>
var conn_options = {
'sync disconnect on unload':false
};
var socket = io.connect('http://localhost:3000',conn_options);
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
</script>
</head>
<body>
</body>
</html>
To detect a disconnect, you need to have some traffic. If your application produces constant traffic, then you could do something like reset a counter each time something is received, and consider the connection failed when the counter runs out.
Otherwise you should be able to use the pings that WebSocket offers. These are not exposed in the browser, but your WebSocket library for Node.js may allow you to turn them on and get a notification if a ping fails.
You can check it in the official library documentation. I don't want to copy-paste it here because it can be out of date soon.

Resources