Flooding WebSocket - javascript

Am new to websocket and i implemented websocket on web application which the server-side is written in java and client-side is javascript. Server send notifications to client via websocket.
I wonder what would happened if client won't be fast enough to handle incoming messages as fast as server is sending them.
For example it is possible that server will be sending about 200 text messages per second, client is slow and is handling 100 messages per second.
I believe that browser queue incoming messages before it's processed but not sure. I what to also know how to check this buffer size and it's limit, and what would happen if buffer limit is reached.
Any idea on how i can simulate this kind of situation, i tried:
webSocket.onmessage = function (message) {
var bool = true;
var datenexexec = Date.now() + 1000;
while(bool) {
if(Date.now() > datenexexec){
bool = false;
}
}
}
but this causes the browser to only hang and later crash.
Thanks for help.

For sending data more rapidly than the client can read it, here's what will eventually happen.
The client receive buffer would fill up
TCP flow control will kick in and the server will be told to stop sending more packets on this socket.
The server will then buffer outgoing packets until flow control restrictions are removed
Eventually the server-side buffer limit will be hit and the underlying TCP would reject the socket write
This will return an error from the TCP send.
Depending upon what server-side library you are using for webSocket, you should get an error from a send operation at some point.
TCP is a reliable protocol so it will just buffer and transmit later until the buffer is full. It shouldn't lose packets by itself (unless the connection drops), but when buffers are full, it will give you an error that it can't send any more because the buffer is full.
As for the client-side code you tried, you can't busy/wait in Javascript for very long. That kills the event loop and eventually brings down the script engine.
The only way for you to simulate this is to try to actually send more packets than the client can process. You can code a "slow" client that takes maybe 250ms to process each packet in a short busy/wait loop and a "fast" server that sends a flood of packets and you should be able to simulate it.

Related

Socket io Client in ReactJS is getting multiple emits from the server

I am building a chat room with some extra features, and I have a socket io server, as well as a socket io client in ReactJS.
I have it so if someone pins a message or changes the settings of the chat room, it emits the changes to the server, the server saves those changes, and then emits them back out to everyone so everyone is synced.
The settings and pinned messages successfully transfer and are communicated, I have console.logs at almost every step of the transfer, the client logs out a single request, the server logs that it emits a single time, but the client logs that it recieved an emit multiple times, sometimes a couple of times like 2-6 requests, sometime it gives out 60 requests. I'm trying to really control the efficiency, but I have no idea what is causing this
I'm not sure it matters but another thing of note is that the client also connects to a native WebSocket server to get messages from another source
what the client generally looks like is:
effect(()=>{
socket.emit('changeSetting', setting)
},[setting])
socket.on('recieveSetting', (arg)=>{
if(arg != setting){
setSetting(arg);
}
})
the server then looks like this:
socket.on('changeSetting', (arg)=>{
storedSetting = arg
socket.emit('recieveSetting', storedSetting)
})
That's the general structure, so I don't think its an issue of the code, more like if reactJS or connecting to the other websocket causes it to get multiple emits

Why some TCP sockets in Node.js take much more time to connect than most others?

I've created small lib tcp-exists to check if tcp endpoint exists. Just to iterate over a network to find anything on special ports.
code of lib on github
But when I am iterating – some of tcp sockets (which creates by lib tcp-exists) take a large amount of time (1-3s instead of 5-20ms) to establish connections on 100% existing endpoints.
import tcpExists from 'tcp-exists'
async function main () {
for (let i = 1; i < 250; ++i) {
let time = performance.now()
const exists = await tcpExists('192.168.1.87', 80, 2000)
time = performance.now() - time
console.log(`time [${i}]:`, time)
if (time > 500) console.log('=====STRANGE=====')
if (!exists) console.log('exists')
}
}
main()
There is no difference between am I checking the same port or different ports on one IP, or am I checking different IPs. Some of that connections will take x100 more time to establish a connection. It can lead to a situation when there is an endpoint that exists, but the function will return false because of a small timeout.
I cannot set a timeout bigger than 25ms for one check. Because if I will want to scan from 192.168.0.0 to 192.168.255.255 (65536 endpoints) — where are most of IP has no endpoint and should be returned false by timeout — and use for example 1s as timeout - then it will take 65536 seconds or ~18hours...
The TCP handshake means that the client sends a SYN to the server, the server ACKs the clients SYN and send its own SYN back (usually both within a single packet, i.e. SYN+ACK) and then the clients reacts to the servers SYN with its own ACK. The speed of the handshakes thus depends on the network latency between client and server and how fast the server reacts to the connection request (SYN). Any packets lost on the way need to be retransmitted after some timeout, which further increases the time for the TCP handshake.
All of this is out of control of the client, i.e. there is no way to speed it up. High performance scanners therefore don't try one connection after the other but try many connections in parallel.

Reusing one opened TCP connection between TCP client and TCP server

There is third party service that expose TCP server to which my node server(TCP client) should establish TCP connection using tls node module.
Being TCP client, node server is also HTTP server at same time, that should act something like proxy between customers coming from web browser and third party TCP server. So common use case would be that browser will send HTTP request to node server from where node server will communicate with TCP server via TCP sockets to gather/construct response and to send it back to browser.
Current solution that i had is that per each customer/each HTTP request coming from web browser new separated TCP connection will be established with TCP server. This solution proved to be bad, wasting time to do SSL handshake every time and TCP server does not allow more than 50 concurrent connections coming from single client. So with this solution it is not possible to have more than 50 customers communicate with node server at once.
What would be something like standard approach to do this thing with tls module in node?
What i'm up to is having one single TCP connection that will be something like always active and that connection will be established in the time when node app will start and what is most important this connection should be reused for many HTTP request coming from web browser.
First concern that i have is how to construct different HTTP responses based on data that is coming from TCP server via TCP raw socket. The good thing is that i can send something like unique token via headers to TCP server when describing which action should be taken on TCP server side.
socket.write(JSON.stringify({
header: {uniqueToken: 032424242, type: 'create something bla bla'},
data: {...}
}))
Having unique token TCP server side guarantee that JSON when combined from different chunks coming over TCP socket and parsed will have this uniqueToken which means im able to map this JSON to HTTP request and to return HTTP response.
My question is does in general TCP protocol guarantee that in this case different successive chunks will belong to the same response that needs to created when those chunks are combined and parsed (when '\n\n' occur)
In another words is there any guarantee that chunks will not be mixed.
(Im aware that it can happen that chunk that contains '\n\n' can belong to two different responses but i will be able to handle that)
If that is not possible than i don't see a way in which first solution (having one connection for one response that needs to be created) can be improved. Only way would be to introduce some connection pooling concept which as far as i know tls module does not provide in any way out of the box.
EDIT based on comments bellow, short version of question:
Lets say that TCP server needs 2 seconds to send all chunks when it receives command create something bla bla
If TCP client send command create something bla bla and immediately after 1 millisecond it send second create something bla bla, is there any chance that could happen that TCP server will write chunk related to second command before it writes all chunks related to first command.
... is there any chance that could happen that TCP server will write chunk related to second command before it writes all chunks related to first command.
If I understand your question correctly you are asking if a write("AB") followed by a write("CD") on the same socket at the server side could result that the clients reads ACDB from the server.
This is not the case if both writes are successful and have actually written all the data to the underlying socket buffer. But, since TCP is a stream protocol with no implicit message boundary the read on the client side could be something like ABCD or AB followed by CD or A followed by BC followed by D etc. Thus to distinguish between the messages from the server you have to add some application level message detection, like an end of message marker, a size prefix or similar.
Also, I restricted the previous statement to both writes are successful and have actually written all the data to the underlying socket buffer. This is not necessarily the case. For example you might functions which do a buffered write like (in C) fwrite instead of write. In this case you usually don't control which parts of the buffer are written at which time so it might be that fwrite("AB") would result in "A" written to the socket while "B" kept in the buffer. If you then have another buffered writer which use the same underlying file descriptor (i.e socket) but not the same buffer then you could actually end up with something like ACDB send to the underlying socket and thus to the client.
This case could even happen if the unbuffered write with not fully successful, i.e. if a write("AB") has only written "A" and signals through the return value that "B" needs to be written later. If you have then a multi-threaded application with insufficient synchronization between threads you could end up with a case that the first threads sends "A" to the socket in the incomplete attempt to write "AB", followed by another thread sending "CD" successfully and then the first thread again completing the send by writing "B". In this case you also end up with "ACDB" on the socket.
In summary: the TCP layer guarantees that the send order is the same as the received order but the user space (i.e. application) needs to make sure that it really sends the data in the right order to the socket. Also, TCP has no message boundary so the distinction of messages inside the TCP stream need to be implemented inside the application by using message boundaries, length prefix, fixed message size or similar.

Correct way to handle Websocket

I've a client to server Websocket connection which should be there for 40 seconds or so. Ideally it should be forever open.
The client continually sends data to server and vice-versa.
Right now I'm using this sequence:
var socket;
function senddata(data)
{
if (!socket)
{
socket = new WebSocket(url);
socket.onopen = function (evt) {
socket.send(data);
socket.onmessage = function (evt) {
var obj = JSON.parse(evt.data);
port.postMessage(obj);
}
socket.oneerror = function (evt) {
socket.close();
socket = null;
}
socket.onclose = function(evt){
socket = null;
}
}
}
else
{
socket.send(data);
}
}
Clearly as per current logic, in case of error, the current request data may not be sent at all.
To be frank it sometimes gives error that websocket is still in connecting state. This connection breaks often due to networking issues. In short it does not work perfectly well.
I've read a better design : How to wait for a WebSocket's readyState to change but does not cover all cases I need to handle.
Also I've Googled about this but could not get the correct procedure for this.
So what is the right way to send regular data through Websockets which handles well these issues like connection break etc?
An event you don't seem to cover is onclose. Which should work really well, since it's called whenever the connection terminates. This is more reliable than onerror, because not all connection disruptions result in an error.
I personally use Socket.IO, it enables real-time bidirectional event-based communication between client and server.
It is event driven. Events such as
on connection :: socket.on('conection',callback);
and
on disconnect :: socket.on('disconnect',callback);
are built in with socket.io so it can help you with your connection concerns. Pretty much very easy to use, check out their site if you are interested.
I use two-layer scheme on client: abstract-wrapper + websocket-client:
The responsibilities of the websocket-client are interacting with a server, recovering the connection and providing interfaces (event-emitter and some methods) to abstract-wrapper.
The abstract-wrapper is a high-level layer, which interacts with websocket-client, subscribes to its events and aggregating data, when the connection is temporary failed. The abstract-wrapper can provide to application layer any interface such as Promise, EventEmitter and so on.
On application layer, I just work with abstract-wrapper and don't worry about connection or data losing. Undoubtedly, it's a good idea to have here information about the status of connection and data sending confirmation, because it's useful.
If it is necessary, I can provide some code for example
This apparently is a server issue not a problem in the client.
I don't know how the server looks like here. But this was a huge problem for me in the past when I was working on a websocket based project. The connection would continuously break.
So I created a websocket server in java, and that resolved my problem.
websockets depend on lots of settings, like if you're using servlets then servlet container's settings matter, if you're using some php etc, apache and php settings matter, for example if you create a websocket server in php and php has default time-out of 30 seconds, it will break after 30 seconds. If keep-alive is not set, the connection wont stay alive etc.
What you can do as quick solution is
keep sending pings to a server after a certain amount of time (like 2 or 3 seconds, so that if a websocket is disconnected it is known to the client so it could invoke onclose or ondisconnect, I hope you know that there is no way to find if a connection is broken other than failing to send something.
check server's keep-alive header
If you have access to server, then it's timeouts etc.
I think that would help

Error while getting messges from sockets in javascript

Hi i am having trouble with creating a socket communication from java script code.
I am always getting error while sending a message or closing the socket from server.
My Socket server code.
// Start listening for connections.
while (true)
{
Console.WriteLine("Waiting for a connection...");
// Program is suspended while waiting for an incoming connection.
Socket handler = listener.Accept();
data = null;
// An incoming connection needs to be processed.
while (true)
{
int bytesRec = handler.Receive(bytes);
data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
break;
}
// Show the data on the console.
Console.WriteLine("Text received : {0}", data);
// Echo the data back to the client.
byte[] msg = Encoding.ASCII.GetBytes(data);
handler.Send(msg);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
JavaScript code:
var connection = new WebSocket('ws://Myip:11000', ['soap', 'xmpp']);
// When the connection is open, send some data to the server
connection.onopen = function () {
connection.send('Ping'); // Send the message 'Ping' to the server
connection.send('your message');
};
// Log errors
connection.onerror = function (error) {
console.log('WebSocket Error ' + error);
};
connection.onclose = function (msg) {
console.log('WebSocket Error ' + msg);
};
It gets connected to server socket, but always gets error while closing or sending a message from server.
If this is really your actual code:
handler.Send(msg);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
…then it's pretty broken. First, you can't assume that Socket.Send() actually sends all the bytes you asked it to. You have to check the return value, and keep sending until you've actually sent all the data.
Second, the initiation of a graceful closure should use SocketShutdown.Send, not SocketShutdown.Both. Specifying "Both" means (among other things) that you're not going to wait for the other end to negotiate the graceful closure. That you're just done and won't even receive any more data, in addition to being done sending.
And of course, the code is calling Close() before the other end has in fact acknowledged the graceful closure (by itself sending any remaining data it wanted to send and then shutting down with "Both").
Is all this the reason for your problem? I can't say for sure, since I have no way to test your actual code. But it's certainly a reasonable guess. If you tear down the connection without waiting after you try to send something, there's not any guarantee that the data will ever leave your machine, and in any case the other end could easily see the connection reset before it gets a chance to process any data that was sent to it.
There aren't a huge number of rules when it comes to socket programming, but what rules exist are there for a reason and are generally really important to follow. You should make sure your code is following all the rules.
(The rest of the code is also different from what I'd consider the right way to do things, but the problems aren't entirely fatal, the way that the over-eager connection destruction is).
I am afraid WebSocket does not work that way.
When the Javascript code connects to the server, it will send a HTTP request as ASCII text. That request will include a HTTP header Sec-WebSocket-Protocol: soap, xmpp, as you are requiring those protocols in your WebSocket creation.
Since your server code does not reply with an appropiate HTTP response accepting the websocket connection, the connection will fail. When you try to send data back, the client will not recognize it as a HTTP response and a error will be thrown.
A websocket is not a regular socket connection, it won't work that way. It requires HTTP negotiation and there is a schema for data framing. I recommend you to go through this article that explains very well how it works: http://chimera.labs.oreilly.com/books/1230000000545/ch17.html
If you are interested in learning how to develop a server, take a look to this tutorial in MDN: https://developer.mozilla.org/en-US/docs/WebSockets/Writing_WebSocket_server I also have an open source WebSocket server in C# you can take a look if you like.

Categories

Resources