node.js hanging tcp connecting attempt - javascript

When massive tcp connecting attempts from node.js javascript client to server while server is restarting, some connecting attempts are hanging. I wrote a simple script to reproduce it:
var net = require('net');
function Conn() {
var conn = new net.Socket({allowHalfOpen: false});
conn.setTimeout(1000);
conn.on('error', function (connectionException) {
console.log('TCP Repeater error: ' + connectionException);
this.connected = false;
});
conn.on('connect', function () {
console.log("connected");
this.connected = true;
});
conn.on('close', function () {
console.log("connection closed");
this.connected = false;
});
conn.on('timeout', function () {
console.log("connection timeout");
this.connected = false;
});
conn.connect(9997, "localhost");
}
for (var i=0;i<400;i++) {
new Conn();
}
Run this script against a starting tcp server. Some attempts are getting errors as server has been started, some attempts are connected after server is started. However, some attempts won't trigger any events and just hanging.
Is there anyway I can kill those hanging attempts? It looks connection timeout won't help as it's for inactivity of established connections. Is there any way to set connecting timeout like setSoTimeout in java?
Thanks

Related

Websocket won't reconnect unless I close the browser tab and restart it

I have a webserver with websockets set up on an ESP8266. The application runs fine on both client and server sides, sending and receiving data. However, if the server side disconnects (power cycle or upload new code), the client (Chrome) won't reconnect to the websocket. I can reload/refresh the web page, and it claims (according to the console log) to be connecting to the websocket, but it does not. The only solution I have found that works is to close the tab, and then restart a new session.
My code is heavily based on this tutorial from Random Nerd Tutorials
var gateway = `ws://${window.location.hostname}/ws`;
var websocket;
function initWebSocket() {
console.log('Trying to open a WebSocket connection...');
websocket = new WebSocket(gateway);
websocket.onopen = onOpen;
websocket.onclose = onClose;
websocket.onmessage = onMessage; // <-- add this line
}
function onOpen(event) {
console.log('Connection opened');
}
function onClose(event) {
console.log('Connection closed');
setTimeout(initWebSocket, 2000);
}
Is there something that is missing from the code above to make it more reliable?
You probably need to use setInterval. Try this, you may have to tweek it a bit.
var gateway = `ws://${window.location.hostname}/ws`;
var websocket, sockTimer=null;
function initWebSocket() {
console.log('Trying to open a WebSocket connection...');
websocket = new WebSocket(gateway);
websocket.onopen = onOpen;
websocket.onerror = onError; //  new
websocket.onclose = onClose;
websocket.onmessage = onMessage; // <-- add this line
}
function onOpen(event) {
clearInterval(sockTimer) // <= better
console.log('Connection opened');
}
function onError() { // <= New
sockTimer = setInterval(init, 1000 * 60);
};
function onClose(event) {
console.log('Connection closed');
//setTimeout(initWebSocket, 2000);
sockTimer = setInterval(initWebSocket, 1000 * 60); // <=new
}

JavaScript: Close WebSocket when server goes offline

I'm using WebSockets to communicate between an ESP8266 (server, using the arduinoWebSockets library) and JavaScript running on a web page (client).
I'd like to notify the user when the connection between the ESP and the browser is lost.
To check if the connection still works, the client sends a "p" message every second, and the server just echoes it. If it the client doesn't receive this echo within a second, it closes the connection (WS.close();).
The WS.onclose event sets a timeout to establish a new connection.
This approach works, but the problem is that when the internet connection is lost, or when the server resets, WS.close() doesn't work as expected.
It just spends 60 seconds in the WebSocket.CLOSING state, and then times out, calling the onclose event one minute too late.
Is there a way to immediately disconnect the WebSocket connection when the server is offline?
let WS;
let WStimeout;
let pingInterval;
startWS();
function startWS() {
console.log("Start WebSocket");
WS = new WebSocket('ws://' + location.hostname + ':81/');
WS.onopen = function () {
pingInterval = setInterval(ping, 1000);
};
WS.onerror = function (err) {
console.log('WebSocket Error ', err);
};
WS.onclose = function (ev) {
console.log("WebSocket Closed ", ev);
clearInterval(pingInterval);
// ... let user know that the connection is lost
WS = null; // delete the current WebSocket
setTimeout(startWS, 5000); // try connecting to WebSocket server again in 5 seconds
}
WS.onmessage = function (ev) {
clearTimeout(WStimeout); // server is still online, clear "ping" timeout
console.log(ev.data);
// ... handle incoming data
}
}
function ping() {
if (!WS || WS.readyState !== WebSocket.OPEN) {
console.log("Connection not open: " + WS.readyState);
return;
}
WS.send("p"); // send ping to server
WStimeout = setTimeout(function () { // if it doesn't respond within a second
if (WS && WS.readyState === WebSocket.OPEN) { // and if the connection is still open
console.error("Ping timed out: closing WebSocket connection ...");
WS.close(); // close the connection
}
}, 1000);
}
Output:
Start WebSocket
p
...
p
* Turned WiFi off and on again *
Ping timed out: closing WebSocket connection ...
Connection not open: 2
... (60 times in total, for 1 minute)
Connection not open: 2
WebSocket Closed
CloseEvent {isTrusted: true, wasClean: false, code: 1006, reason: "", type: "close", …}
Start WebSocket
p
...

error establishing connection between js client and python server in chrome extension

I am trying to connect between js client and python server in chrome extension platform, but getting error in the connection establishment.
It is important to note that the code worked in cmd test, but when I tried to make the connection in the chrome extension, it gets an error. So if someone had already deal with something similar, please check the code and help me to figure what is wrong with it.
I used serversocket module.
Here is the server:
clients = []
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
if self not in clients:
clients.append(self)
self.data = self.request.recv(1024).strip()
if self.data == "":
clients.remove(self)
print(self.data)
arr=self.data.split('~')
result=algo(arr)
self.request.send(result)
if _name_ == "__main__":
HOST, PORT = '127.0.0.1', 6169
server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
print("hi")
# interrupt the program with Ctrl-C
server.serve_forever()
The alerts and some of the if are for checking
and the client:
var st="password11"+"~"+"www.google.com"+"~"+"1656226256";
//"wss://"+HOST+":"+PORT+"/"
if ('WebSocket' in window){
alert("websocket");
var socket = new WebSocket("wss://127.0.0.1:6169/", ['soap', 'xmpp']);
socket.onopen = function (evt) {
alert("connection opened");
socket.send(st);
};
socket.onmessage = function (evt) {
alert("Message from remote server : "+evt.data);
socket.close();
};
socket.onerror = function (evt) {
alert(evt.data);
};
socket.onclose = function (evt) {
alert("connection closed");
};
}
else {
alert("web socket is not supported")
}

fail to connect localhost:8081 using node.js

I have opened the server.js and the address:http://localhost:8081 on my browser. But then a text "Upgrade Required" appeared at the top left conern of the website.
What is the problem of that? What else do I need to upgrade?
Here is the server.js:
var serialport = require('serialport');
var WebSocketServer = require('ws').Server;
var SERVER_PORT = 8081;
var wss = new WebSocketServer({
port: SERVER_PORT
});
var connections = new Array;
SerialPort = serialport.SerialPort,
portName = process.argv[2],
serialOptions = {
baudRate: 9600,
parser: serialport.parsers.readline('\n')
};
if (typeof portName === "undefined") {
console.log("You need to specify the serial port when you launch this script, like so:\n");
console.log(" node wsServer.js <portname>");
console.log("\n Fill in the name of your serial port in place of <portname> \n");
process.exit(1);
}
var myPort = new SerialPort(portName, serialOptions);
myPort.on('open', showPortOpen);
myPort.on('data', sendSerialData);
myPort.on('close', showPortClose);
myPort.on('error', showError);
function showPortOpen() {
console.log('port open. Data rate: ' + myPort.options.baudRate);
}
function sendSerialData(data) {
if (connections.length > 0) {
broadcast(data);
}
}
function showPortClose() {
console.log('port closed.');
}
function showError(error) {
console.log('Serial port error: ' + error);
}
function sendToSerial(data) {
console.log("sending to serial: " + data);
myPort.write(data);
}
wss.on('connection', handleConnection);
function handleConnection(client) {
console.log("New Connection");
connections.push(client);
client.on('message', sendToSerial);
client.on('close', function () {
console.log("connection closed");
var position = connections.indexOf(client);
connections.splice(position, 1);
});
}
function broadcast(data) {
for (c in connections) {
connections[c].send(data);
}
}
OK, websockets...
The "upgrade required" status marks the start of a websocket handshake. Normally your client sends this first to the WS server. The server answers in a pretty similar manner (details here : https://www.rfc-editor.org/rfc/rfc6455 ), and then proceed to pipe the actual data.
Here, you're opening a connection from your client as regular http, sending a simple GET. What you see on the screen is the server dumbly proceeding with an already corrupted handshake.
That's not how you open a WS client side connection. You don't usually open WS pages from the browser. It ought to be opened from a JavaScript call, such as new WebSocket(uri). So what you want is a regular http server on another port, that serves a page containing the necessary Javascript to open the actual WS connection and do something useful with its data. You'll find a clean example here : http://www.websocket.org/echo.html

Socket IO reconnect?

How to reconnect to socket io once disconnect has been called?
Here's the code
function initSocket(__bool){
if(__bool == true){
socket = io.connect('http://xxx.xxx.xxx.xxx:8081', {secure:false});
socket.on('connect', function(){console.log('connected')});
socket.on('disconnect', function (){console.log('disconnected')});
}else{
socket.disconnect();
socket = null;
}
}
If I do initSocket(true), it works. If I do initSocket(false), it disconnects. BUT THEN if I try to reconnect using initSocket(true), the connection does not work anymore. How can I get the connection to work?
Well, you have an option here ...
The first time you initialize the socket value you should connect with io.connect,
The next time ( after you've called disconnect once ), you should connect back with socket.socket.connect().
So your initSocket, should be something like
function initSocket(__bool){
if(__bool){
if ( !socket ) {
socket = io.connect('http://xxx.xxx.xxx.xxx:8081', {secure:false});
socket.on('connect', function(){console.log('connected')});
socket.on('disconnect', function (){console.log('disconnected')});
} else {
socket.socket.connect(); // Yep, socket.socket ( 2 times )
}
}else{
socket.disconnect();
// socket = null; <<< We don't need this anymore
}
}
I know you already have an answer, but I arrived here because the socket.IO client reconnection feature is broken in node at the moment.
Active bugs on the github repo show that lots of people aren't getting events on connect failure, and reconnect isn't happening automatically.
To work around this, you can create a manual reconnect loop as follows:
var socketClient = socketioClient.connect(socketHost)
var tryReconnect = function(){
if (socketClient.socket.connected === false &&
socketClient.socket.connecting === false) {
// use a connect() or reconnect() here if you want
socketClient.socket.connect()
}
}
var intervalID = setInterval(tryReconnect, 2000)
socketClient.on('connect', function () {
// once client connects, clear the reconnection interval function
clearInterval(intervalID)
//... do other stuff
})
You can reconnect by following client side config.
// 0.9 socket.io version
io.connect(SERVER_IP,{'force new connection':true });
// 1.0 socket.io version
io.connect(SERVER_IP,{'forceNew':true });
This is an old question, but I was struggling with this recently and stumbled here. Most recent versions of socket.io (>2.0) doesn't have the socket.socket property anymore as pointed out here.
I am using socket.io-client 2.2.0 and I was facing a situation where the socket seems to be connected (property socket.connected = true) but it wasn't communicating with the server.
So, to fix that, my solution was call socket.close()and socket.open. These commands force a disconnection and a new connection.
I had an issue with socket-io reconnect. May be this case will help someone. I had code like this:
var io = require('socket.io').listen(8080);
DB.connect(function () {
io.sockets.on('connection', function (socket) {
initSockets(socket);
});
});
this is wrong, becase there is a delay between open port assigned callbacks. Some of messages may be lost before DB gets initialized. The right way to fix it is:
var io = null;
DB.connect(function () {
io = require('socket.io').listen(8080);
io.sockets.on('connection', function (socket) {
console.log("On connection");
initSockets(socket);
});
});

Categories