when my device is disconnected from server or device don't have internet connection, after emitting multiple socket to server that cause of reply to all sockets after connecting to server
for example:
1- client disconnected from server, i click multiple on button to emit data for example 10 click as request
2- after connecting client to server, server reply on 10 response
how can i manage this process?
problem resolved, Thanks to #farhadamjady
var mySocket = io.connect('http://192.168.1.4:8080/backend_app', {transports: ['websocket'], reconnection: true});
mySocket.on('connect', function () {
mySocket.sendBuffer=[]
console.log('Connected!');
});
Related
We currently have a Laravel CMS server that sends a request to another Laravel websocket server which then broadcasts to multiple IoT devices listening on their individual channels for requests. Everything works perfectly.
So it looks like this:
CMS server -> Socket server -> devices
I am trying to initiate these websocket requests from a third server which is not running Laravel, it's just running core PHP and JavaScript. I looked in my browser's Network tab to spy on the websocket connection from a legitimate request, copied it exactly, the connection and subscription succeed but when I send the requests over the socket from my test script, nothing happens. It's literally the exact same socket request over the same channel on the same connection, just with a different socket ID. How could this fail?
I thought maybe it was only accepting requests from that specific server so I copied my test script to that server and still no response. I don't know much about web sockets, could someone please help me understand how I can spoof these messages without using Laravel?
If you're wondering what I'm actually up to, we're decommissioning this CMS server for our new CMS we built in core PHP so we no longer have Laravel as an option but I don't want to rewrite the socket server which uses Laravel, that can stay. I just need to interface with it any way possible. I have full SSH and DNS access to anything I need to configure.
Here is my test script, I've tried about 50 of them I found on Google, none of them give me a response from my specific socket server, besides the connection successful and subscription successful responses.
<script>
let socket = new WebSocket('wss://subdomain.domain.ca:6001/app/apikeyyyyy?protocol=7&client=js&version=4.4.0&flash=false');
var message = {
channel:"aaaaaa.bbbbbbbb",
event:"1000",
data:"{\"channelName\":\"aaaaaa.bbbbbbbb\",\"message\":{\"msgId\":\"\",\"cmd\":\"help\",\"timestamp\":1663616905529,\"request_id\":\"\",\"device_id\":\"\"},event:\"1000\",timestamp:1663616905529,request_id:\"\",device_id:\"\"}"
};
socket.onopen = function(e) {
var data_json = {
event:'pusher:subscribe',
data:{
channel:'aaaaaa.bbbbbbbb',
}
};
socket.send(JSON.stringify(data_json));
socket.send(JSON.stringify(message));
};
socket.onmessage = function(event) {
console.log("Response: " + event.data);
};
socket.onclose = function(event) {
if (event.wasClean) {
alert(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`);
} else {
// e.g. server process killed or network down
// event.code is usually 1006 in this case
alert('[close] Connection died');
}
};
socket.onerror = function(error) {
alert(`[error] ${error.message}`)
};
</script>
I obviously removed the channel name, domain and application key for security but the rest is accurate. And here's what I see in my browser console:
Response: {"event":"pusher:connection_established","data":"{\"socket_id\":\"166323189.236668505\",\"activity_timeout\":30}"}
Response: {"event":"pusher_internal:subscription_succeeded","channel":"aaaaaa.bbbbbbbb"}
When I send a request from the (working) CMS server, I get a OK response from the socket server and the related device will reboot or whatever I asked it to do. When I send the exact same response from my test script, I see the request get logged in the websockets.log file on the socket server but no response is logged like it is with the requests from the CMS server. And no response prints in the browser console even though I do see the responses print in the browser console for my test script when I send them from the CMS so I know the subscription is working correctly. Also the devices do not reboot.
// client.js
const webSocket = new WebSocket('wss://127.0.0.1:8081');
webSocket.addEventListener('open', (message) => {
alert(message);
})
const text = document.getElementById('text');
const button = document.getElementById('button');
button.onclick = () => {
webSocket.send(text.value);
}
// server.js
import { Server } from 'net';
const server = new Server();
server.on('connection', (socket) => {
console.log(socket);
socket.on('data', (data) => {
})
});
server.listen(8081, '127.0.0.1', () => {
console.log('Server running at port 8081');
});
The problem that I'm facing is:
When I load the page the socket is printed in the console of the server (I can get the remote address and remote port)
No matter what I do, the connection in the client is always pending. I tried Chrome, Brave, Mozilla and Safari and no one seems to work.
What am I missing? I tried to not send the message until the connection is ready, but I never get that state in my PC. The alert in the client never pops, even if I establish the onopen property without an event.
Uncaught DOMException: Failed to execute 'send' on 'WebSocket': Still in CONNECTING state.
at button.onclick
A webSocket client must connect to a webSocket server. webSocket is a specific connection algorithm (that starts with an http request and then switches to the webSocket protocol) and a specific data format. So, a webSocket client must have a webSocket server to connect to. Your server is a generic TCP server that does not support webSocket connections.
The client will initially establish a TCP socket to your server, then send an http request over that socket, and then it will sit there waiting for an appropriate response to the http request it sent. Since your server never sends that response, it will just sit there waiting until eventually it will timeout and close the socket. This is why you see it stuck in the pending state. It's still waiting for the rest of the webSocket connection sequence to happen and it never does.
If you're curious how the webSocket connection scheme and data format work, you can see a nice description of it here.
Relevant StackOverflow answers:
How does WebSockets server architecture work?
What's the difference between WebSocket and plain socket communication?
Do websocket implementations use http protocol internally?
Overview of webSocket connection scheme
How WebSocket server handles multiple incoming connection requests?
I want to have an HTTP server which allows me to establish a TCP connection with a remote computer whenever I specify a given path inside the URL in a browser.
For example... let's say that I have a computer with a public IP address and a hostname as the server (mydomain.com:9000) and a remote computer with a local IP address (192.168.0.1) connected to the server. Somehow I want to establish a TCP connection between a client and the remote computer. And to make it easier just enter an URL with a path (mydomain.com:9000/remote). NOT WITH ANOTHER PORT! Also, I want the connection to be done if and only if that path is entered.
To illustrate a little better how the system works:
_________ _________ _________
| | internet | | local network | |
|_______| ----------> |_______| ----------> |_______|
____|____ <---------- ____|____ <---------- ____|____
client server remote computer
sends http request checks path gets http request
mydomain.com:9000/remote establishes TCP connection handles request
I made some code with node js to make sure that the connection was possible. And it is, now I only have to be able to check the path and establish the connection only then. My code is a simple TCP tunneling proxy and it works fine. But when I try to implement the path it doesn't.
//Import modules
const net = require('net');
const http = require('http');
let inpath = false;
// Create proxy server
const proxy = http.createServer( function(req,res){
console.log(req.url);
//Check path
if(req.url == '/remote')
inpath = true;
});
proxy.on('connection', client => {
if(inpath)
{
const remote = new net.Socket();
//Establish connection
remote.connect(80,'192.168.0.100');
client.on('error', err => {
console.log('Error: ' + err);
proxy.close();
});
//Port-forwarding
client.pipe(remote);
remote.pipe(client);
}
});
proxy.listen(9000);
Is there a way to do this?
In your code, you'll find that the connection event is firing well before your request handler callback is being called. This is because a TCP connection (for which the connection event is triggered) occurs from a client connecting before the client makes its HTTP request. Additionally, what you have isn't really going to work reliably because HTTP keep-alive may mean that multiple requests will come down a single TCP connection.
To fix this, you need to move all of that code you have in your connection event up to your HTTP request handler.
You'll run into other problems though, in that now your code is effectively handling the HTTP request/response, so you'll need to parse and rebuild the request/response data when communicating with the upstream server.
If you truly do wish to handle this at the TCP level, don't use http.createServer(). Use net instead and create a normal TCP server. Then, parse the request data yourself and if you find the certain path you want in the request, make the proxying TCP connection, and be sure to send down the existing buffers so that the upstream server can get the full HTTP request.
I use node.js (Express) with server-sent events. I would like to close the event stream by closing the sse HTTP connection. Given the folllwing function:
router.get('/sse', function (req, res) {
});
how can this be achieved?
use this
res.end();
and it will work to close connection
How to hang up in ExpressJS
Ⅰ. End the response, keeping the socket connection alive.
response.end();
Ⅱ. “Could you please hang up first?”
Request the client to initiate the TCP socket connection termination sequence.
response.set("Connection", "close"); // Note: this is an HTTP header.
Ⅲ. Gently close the socket connection.
“Hey, I’ll be hanging up now, ’kay?”
response.connection.end();
socket.end([data[, encoding]][, callback])
Half-closes the socket. i.e., it sends a FIN packet. It is possible the server will still send some data.
See writable.end() for further details.
Ⅳ. Just hang up on the client aggressively. No FIN packet, even.
response.connection.destroy();
socket.destroy([error])
Ensures that no more I/O activity happens on this socket. Destroys the stream and closes the connection.
See writable.destroy() for further details.
Selected answer is incorrect, res.end() ends the response and writes to the socket. But it doesn't close the TCP connection.
You need to get the underlying connection from the res object and call end on it to close it.
res.connection.end();
I am using regular javascript WebSockets to communicate with my server running on localhost. My server is running node.js and using the websocket from here:
https://github.com/einaros/ws/blob/master/doc/ws.md
The socket's connect and can send messages, however the socket closes on the server side as soon as the onMessage function returns. The socket is still open on the client side. My goal is to keep a reference to the socket to be able to send messages from the server later on. Is this possible with node.js and 'ws' websockets? Thanks!
// Listen to sockets for chrome extension
var WebSocketServer = require('ws').Server
, wss = new WebSocketServer({port: 9090});
wss.on('connection', function(ws) {
ws.on('message', function(message) {
ws.send("received")
});
ws.on('close', function(message) {
console.log('CLOSED!');
});
});
On connection output is:
received
CLOSED!