I use node.js and socket.io to create a real time web application. I will give the users full control of the socket connection, like manual disconnect and (re)connect.
function socket_connect()
{
console.log('func socket_connect');
socket = io.connect('http://url/to/the/app');
}
function socket_reconnect()
{
console.log('func socket_reconnect');
socket_connect();
}
function socket_disconnect ()
{
console.log('func socket_disconnect');
if (socket) socket.disconnect();
}
On client start up the socket_connect() function works fine, but after using socket.disconnect(), no new connection starts.
You can reconnect by following client side config.
// for socket.io version 1.0
io.connect(SERVER_IP,{'forceNew':true });
It works now, with socket.socket.reconnect()
function socket_connect()
{
console.log('func socket_connect');
socket = io.connect('http://url/to/the/app');
}
function socket_reconnect()
{
console.log('func socket_reconnect');
socket.socket.reconnect();
}
function socket_disconnect ()
{
console.log('func socket_disconnect');
if (socket) socket.disconnect();
}
Related: https://github.com/LearnBoost/socket.io-client/issues/251
If you're using Socket.io 1.0, try using the io manager on the socket to handle manual disconnection and reconnection.
// Connect to socket.io
var socket = io.connect('url');
function manual_disconnect() {
socket.io.disconnect();
}
function manual_reconnect() {
socket.io.reconnect();
}
The reconnecting_attempt, reconnecting, reconnected and connected events on the socket should all be emitted afterwards.
Related
I have a simple client-side script like this:
function connect() {
const { contextBridge } = require('electron');
var ws = new WebSocket('ws://localhost:3000');
ws.onerror = (error) => {
console.error(`Lost connection to server. Reason: ${error.message}`);
console.error('Attempting to reconnect...');
ws.close();
}
ws.onclose = (e) => {
setTimeout({
connect();
}, 500);
}
ws.addEventListener('open', () => {
console.log('Connected to server!');
});
// Some other stuff to call functions via the browser console
const API = {
ws_isOpen: () => { return ws.readyState === ws.OPEN }
}
contextBridge.exposeInMainWorld('api', API);
function send_msg(msg) {
// Process some data...
ws.send(msg);
}
}
connect();
It works normally when the server is running and it's trying to connect, or when the server is rebooting and it's trying to connect for the first time, but not while it's connected. What I mean is that, if I were to suddenly shut the server down while the client is being connected to it, it attempts to try to reconnect as usual and the success message does pop up. However, if I type in window.api.ws_isOpen() in the browser console, it returns false. When I try to send a message, an error pops up saying something like Websocket is already in CLOSING or CLOSED stage. I tried changing the ws variable type to let and const but it doesn't work.
Turns out the answer is really simple. For some reason, when I put the ws variable outside the connect() function and modify it in the function, it works. I'm guessing it kinda re-declares/re-new the ws variable. It looks something like this:
var ws = null;
function connect() {
ws = new WebSocket('ws://localhost:3000');
// the exact same as above here....
}
connect();
After rebooting the server and letting it reconnect:
>> window.api.ws_isOpen()
true
I feel like I'm supposed to know how this works...
I am using Azure Pub-Sub Service for Chatting module in a ReactApplication, I am creating this connection using Websocket.
let ws = new WebSocket(token.url);
ws.onmessage = (data) => {
//Messages Logic
}
when i am in other tabs, or in the sametab for longer time(more than 40-45 mins). I am not receiving messages, but when i refresh the page and websocket initialization code gets executed again and then i receive messages again. Any Suggestions?
Use this technique :
function connect() {
var ws = new WebSocket('ws://localhost:8080');
ws.onopen = function() {
// subscribe to some channels
ws.send(JSON.stringify({
//.... some message the I must send when I connect ....
}));
};
ws.onclose = function(e) {
console.log('Socket is closed. Reconnect will be attempted in 1 second.', e.reason);
setTimeout(function() {
connect();
}, 1000);
};
I'm fairly new to Javascript and am trying to wrap my head around async, promises, etc.
I have an application running a TCP API (non-HTTP) on the localhost. I'm building an Electron app to interact with this API. I need to send a single request to the API every second and retrieve a single JSON object it returns.
I'm able to do this successfully (for while) by running something like this:
const net = require('net');
function apiCall() {
if (running) {
setTimeout(() => {
// Send the request
request = '{"id":1,"jsonrpc":"2.0","method":"getdetails"}'
socketClient = net.connect({host:'localhost', port:8888}, () => {
socketClient.write(request + '\r\n');
});
// Listen for the response
var response;
socketClient.on('data', (data) => {
response = JSON.parse(data).result;
updateUI(response);
socketClient.end();
});
// On disconnect
socketClient.on('end', () => {
console.log('Disconnected from API');
});
apiCall();
}, refreshRate)
}
}
After running this for an extended amount of time, it appears that the API server is crashing:
Error: connect ECONNREFUSED 127.0.0.1:8888
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1146)
Unfortunately, I have no control over the API server or its source code. I'd like some clarification on whether my client might be causing the API server to crash by sending requests this way.
Should I be opening and closing the connection for each request or keep it open and send requests only every second?
If I should be keeping the connection open, how can I do this, and do I need to worry about keep-alive?
It looks like that every time you call apiCall you are creating a new socket client and you are not removing the old socket client instances. This is a memory leak and it will cause the application to crash after running for some time
You can keep a running connection instead like below
const net = require("net");
const { once } = require("events");
let socketClient;
function apiCall() {
if (running) {
setTimeout(async () => {
const request = '{"id":1,"jsonrpc":"2.0","method":"getdetails"}';
// Create the socket client if it was not already created
if (!socketClient) {
socketClient = net.connect({ host: "localhost", port: 8888 });
// On disconnect
socketClient.on("end", () => {
console.log("Disconnected from API");
socketClient.destroy();
socketClient = null;
});
// Wait until connection is established
await once(socketClient, "connect");
}
// Send the request
socketClient.write(request + "\r\n");
// Listen for the response
const data = await once(socketClient, "data");
const response = JSON.parse(data).result;
updateUI(response);
apiCall();
}, refreshRate);
}
}
In my client-side node code, I have something like this:
var socket = io('//localhost:1337');
$(function() {
if ( !socket.connected )
NodeOfflineError();
});
Now, let's say I had a NodeBackOnlineAlert() function to go along with the NodeOfflineError() function, how would I know when to call it?
Is there a listener for the polling that checks whether the server is live?
You can have listeners that run the function and have a function to reconnect when the socket is disconnected:
socket.on("disconnect", function() {
NodeOfflineError();
socket.socket.reconnect();
});
socket.on("connect", function() {
NodeOnlineAlert()
});
socket.on("reconnect", function() {
NodeBackOnlineAlert()
});
You can use the listener events of socket io (assuming you use socket io)
const socket = io('//localhost:1337')
$(() => {
socket.on('connected', socket => {
console.log('connected!')
socket.on('disconnect', () => {
NodeOfflineError()
})
})
socket.on('reconnect', () => {
NodeBackOnlineAlert()
})
})
http://socket.io/docs/ Check the part where it says 'Sending and receiving events' also http://socket.io/docs/client-api/ :)
You could use Server Sent Events: https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events. The MDN guide should have everything you need to implement them (they're quite simple!). This library might prove useful for your server: https://www.npmjs.com/package/sse
I have log messages that are being emitted from server to client and that are coming consistently from server and logging to client, Now I have additional functionality to stop and play logs to give some controls to user, So I am thinking on stop to disconnect socket.io connection and on play start socket.io connection again, First i am trying with stop to disconnect connection but i could not emit message to server ,any idea what is wrong with below code or any better solution to achieve these task ?
main.html
<button type="button" class="btn btn-success" ng-click="stopLogs()">stop</button>
ctrl.js
$scope.stopLogs = function(){
socket.emit('end');
}
angularSOcketFactory.js
angular.module('App').factory('socket', function ($rootScope) {
'use strict';
var socket = io.connect('http://localhost:3000');
return {
on: function (eventName, callback) {
socket.on(eventName, function () {
var args = arguments;
$rootScope.$apply(function () {
callback.apply(socket, args);
});
});
},
emit: function (eventName, data, callback) {
socket.emit(eventName, data, function () {
var args = arguments;
$rootScope.$apply(function () {
if (callback) {
callback.apply(socket, args);
}
});
})
}
};
});
server.js
var io = require('socket.io')(server);
io.sockets.on('connection',function(){
// Producer.startProducer();
ditconsumer.start(function(value){
io.emit('ditConsumer',value)
});
io.sockets.on('end', function() {
socket.disconnect();
console.log('it will disconnet connection');
});
});
This code is wrong:
io.sockets.on('end',function () {
console.log('this will disconnet socket connection');
io.sockets.disconnect();
});
You need to apply that event listener to one specific socket and then you need to disconnect one specific socket.
You don't show the general context of your server code, but it could be done like this:
io.on('connection', function(socket) {
socket.on('end', function() {
socket.disconnect();
});
});
You could also just have the client disconnect directly rather than asking the server to do it for you.