// 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?
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.
As the title says I'm trying to connect to a website their WebSocket to get live updates. However I've tried everything, and all it does is the WebSocket immediately disconnects after connecting. I've checked their version of the connection to the WebSocket, they do not reply with anything after the onopen event. I've tried setting the origin in case of them not accepting any connections from origins other than their own.
I'm trying to do this within NodeJS with the ws module. I'm trying to reach the WebSocket of https://rollbit.com (wss://ws.rollbit.com/);
Code
const WebSocket = require('ws');
const ws = new WebSocket('wss://ws.rollbit.com/', {
origin: 'https://rollbit.com'
});
ws.on('open', function open() {
console.log('connected');
});
ws.on('close', function close() {
console.log('disconnected');
});
I've also attempted to do this from within the browser, it works perfectly when I do it from the console when being on their site, when changing to another site and running the code there - it fails. I've tried cookies as well..
Result
connected
disconnected
Any ideas of what I'm missing here?
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!');
});
I created a WebSocket client in JavaScript
if ("WebSocket" in window) {
ws = new WebSocket(url);
ws.binaryType = "arraybuffer";
} else if ("MozWebSocket" in window) {
ws = new MozWebSocket(url);
ws.binaryType = "arraybuffer";
}
and a WebSocket server application. For certain cases I programmed the server to reject the connection request and provide an error code.
In e.g. Firefox Console then a message is shown
Firefox can't establish a connection to the server at ws://123.123.123.123:1234/.
and it provides the status code
HTTP/1.1 403
which is the error code that I have sent by my WebSocket server.
My question is: how can I read this status code in my JavaScript client?
ws.onerror = function(e) {
console.log(e);
};
ws.onclose = function(e) {
console.log(e);
};
are both called, but none of the Event objects contains this error code.
The spec forbids reading the HTTP status code (or anything like it) from the WebSocket object because otherwise the WebSocket object could be used to probe non-WebSocket endpoints, which would be a security issue:
User agents must not convey any failure information to scripts in a way that would allow a script to distinguish the following situations:
A server whose host name could not be resolved.
A server to which packets could not successfully be routed.
A server that refused the connection on the specified port.
A server that failed to correctly perform a TLS handshake (e.g., the server certificate can't be verified).
A server that did not complete the opening handshake (e.g. because it was not a WebSocket server).
A WebSocket server that sent a correct opening handshake, but that specified options that caused the client to drop the connection (e.g. the server specified a subprotocol that the client did not offer).
A WebSocket server that abruptly closed the connection after successfully completing the opening handshake.
— https://www.w3.org/TR/websockets/#feedback-from-the-protocol
There is another way to do it though!
The WebSocket protocol allows for custom close codes:
4000-4999
Status codes in the range 4000-4999 are reserved for private use and thus can't be registered. Such codes can be used by prior agreements between WebSocket applications. The interpretation of these codes is undefined by this protocol.
— https://www.rfc-editor.org/rfc/rfc6455#section-7.4.2
In your server-side logic, even when you ultimately want to reject the connection (like say the user is currently unauthenticated), do this instead:
Accept the WebSocket connection
Immediately close the connection with a custom close status
The client can now look at the CloseEvent.code to know why the connection was rejected.
You don't need to do this every time the server wants to reject a WebSocket connection. For example, I'd still reject the connection with a 4xx HTTP status if the request isn't a proper WebSocket request, or for security reasons (like if the anti-CSWSH Origin check fails). You only need to use the WebSocket close status for cases that you want the client-side logic to handle.
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!