Are TCP Connections resource intensive? - c#

I have a TCP server that gets data from one (and only one) client. When this client sends the data, it makes a connection to my server, sends one (logical) message and then does not send any more on that connection.
It will then make another connection to send the next message.
I have a co-worker who says that this is very bad from a resources point of view. He says that making a connection is resource intensive and takes a while. He says that I need to get this client to make a connection and then just keep using it for as long as we need to communicate (or until there is an error).
One benefit of using separate connections is that I can probably multi-thread them and get more throughput on the line. I mentioned this to my co-worker and he told me that having lots of sockets open will kill the server.
Is this true? Or can I just allow it to make a separate connection for each logical message that needs to be sent. (Note that by logical message I mean an xml file that is of variable length.)

It depends entirely on the number of connections that you are intending to open and close and the rate at which you intend to open them.
Unless you go out of your way to avoid the TIME_WAIT state by aborting the connections rather than closing them gracefully you will accumulate sockets in TIME_WAIT state on either the client or the server. With a single client it doesn't actually matter where these accumulate as the issue will be the same. If the rate at which you use your connections is faster than the rate at which your TIME_WAIT connections close then you will eventually get to a point where you cannot open any new connections because you have no ephemeral ports left as all of them are in use with sockets that are in TIME_WAIT.
I write about this in much more detail here: http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html
In general I would suggest that you keep a single connection and simply reopen it if it gets reset. The logic may appear to be a little more complex but the system will scale far better; you may only have one client now and the rate of connections may be such that you do not expect to suffer from TIME_WAIT issues but these facts may not stay the same for the life of your system...

The initiation sequence of a TCP connection is a very simple 3 way handshake which has very low overhead. No need to maintain a constant connection.
Also having many TCP connections won't kill your server so fast. modern hardware and operating systems can handle hundreds of concurrect TCP connections, unless you are afraid of Denial of service attacks which are out of the scope of this question obviously.

If your server has only a single client, I can't imagine in practice there'd be any issues with opening a new TCP socket per message. Sounds like your co-worker likes to prematurely optimize.
However, if you're flooding the server with messages, it may become an issue. But still, with a single client, I wouldn't worry about it.
Just make sure you close the socket when you're done with it. No need to be rude to the server :)

In addition to what everyone said, consider UDP. It's perfect for small messages where no response is expected, and on a local network (as opposed to Internet) it's practically reliable.

From the servers perspective, it not a problem to have a very large number of connections open.
How many socket connections can a web server handle?
From the clients perspective, if measuring shows you need to avoid the time initiate connections and you want parallelism, you could create a connection pool. Multiple threads can re-use each of the connections and release them back into the pool when they're done. That does raise the complexity level so once again, make sure you need it. You could also have logic to shrink and grow the pool based on activity - it would be ashame to hold connections open to the server over night while the app is just sitting their idle.

Related

Winsock IOCP Weird Behaviour On Disconnect Flood

I'm programming a Socket/Client/Server library for C#, since I do a lot of cross-platform programming, and I didn't find mono/dotnet/dotnet core enough efficient in high-performance socket handling.
Sice linux epoll unarguably won the performance and usability "fight", I decided to use an epoll-like interface as common API, so I'm trying to emulate it on Windows environment (windows socket performance is not that important for me than linux, but the interface is). To achieve this I use the Winsock2 and Kernel32 API's directly with Marshaling and I use IOCP.
Almost everything works fine, except one: When I create a TCP server with winsock, and connect to it (from local or from a remote machine via LAN, does not matter) with more than 10000 connections, all connections are accepted, no problem at all, when all connections send data (flood) from the client side to the server, no problem at all, server receives all packets, but when I disconnect all clients at the same time, the server does not recognize all disconnection events (i.e. 0 byte read/available), usually 1500-8000 clients stuck. The completion event does not get triggered, therefore I can not detect the connection loss.
The server does not crash, it continues accept new connections, and everything works as expected, only the lost connections do not get recognized.
I've read that - because using overlapped IO needs pre-allocated read buffer - IOCP on reading locks these buffers and releases the locks on completion, and if too many events happen in the same time it can not lock all affected buffers because of an OS limit, and this causes IOCP hang for indefinite time.
I've read that the solution to this buffer-lock problem is I should use a zero-sized buffer with null-pointer to the buffer itself, so the read event will not lock it, and I should use real buffer only when I read real data.
I've implemented the above workaround and it works, except the original problem, after disconnecting many-thousands of clients in the same time, a few-thousand stuck.
Of course I keep up the possibility my code is wrong, so I made a basic server with dotnet's built in SocketAsyncEventArgs class (as the official example describes), that basically does the same using IOCP, and the results are the same.
Everything works fine, except the thousands of client disconnecting in the same time, a few-thousand of disconnection (read on disconnect) events does not get recognized.
I know I should do IO operation and check the return value if the socket is still can perform the IO, and if not, then disconnect it. The problem is in some cases I have nothing to tell the socket, I just receive data, or if I do it periodically this would be almost the same as polling, and would cause high load with thousands of connections, wasted CPU work.
(I use closing the clients numerous closing methods, from gaceful disconnection to proper TCP Socket closing, both on windows and linux clients, results are always the same)
My questions:
Is there any known solution to this problem?
Is there any efficient way to recognize TCP (graceful) connection closing by remote?
Can I somehow set a read-timeout to overlapped socket read?
Any help would be appreciated, thank You!

Any Downside to Increasing "maxconnection" Setting in system.net?

Our system was having a problem with WCF connections being limited, which was solved by this answer. We added this setting to the client's web.config, and the limit of two concurrent connections went away:
Outside of the obvious impacts (e.g. overloading the server), are there any downsides to setting this limit to a number (possibly much) higher than the default "2"? Any source on the reasoning for having the default so low to begin with?
In general, it's OK to raise the client connection limit, with a few caveats:
If you don't own the server, then be careful because your client app might be confused with a DoS attack which might lead to your client IP address being blocked by the server. Even if you own the server, this is sometimes a risk-- for example, we've had cases where a bug in our app's login page caused multiple requests to be issued when the user held down the Enter key. This caused these users to get blocked from our app because of our firewall's DoS protection!
Connections aren't free. They take up RAM, CPU, and other scarce resources. Having 5 or 10 client connections isn't a problem, but when you have hundreds of open client connections then you risk running out of resources on the client.
Proxies or edge servers between client and server may impose their own limits. So you may try to open 1,000 simultaneous connections only to have #5 and later refused by the proxy.
Sometimes, adding more client connections is a workaround for an architectural problem. Consider fixing the architectural problem instead. For example, if you're opening so many connections because each request takes 10 minutes to return results, then you really should look at a more loosely-coupled solution (e.g. post requests to a server queue and come back later to pick up results) because long-lived connections are vulnerable to network disruption, transient client or server outages, etc.
Being able to open many simultaneous connections can make it risky to restart your client or server app, because even if your "normal" load is only X requests/sec, if either client or server has been offline for a while, then the client may try to catch up on pending requests by issuing hundreds or thousands of requests all at once. Many servers have a non-linear response to overload conditions, where an extra 10% of load may reduce response time by 100%, creating a runaway overload condition.
The solution to all these risks is to carefully load-test both client and server with the maximum # of connections you want to support... and don't set your connection limit higher than what you've tested. Don't just crank the connection limit to 1,000,000 just because you can!
To answer the other part of your question, the default limit of 2 connections goes back to a very old version of the HTTP specification which limited clients to 2 connections per domain, so that web browsers wouldn't swamp servers with a lot of simultaneous connections. For more details, see this answer: https://stackoverflow.com/a/39520881/126352

Websockets persistant connection

Since the connection is persistent, i understand a lot of network congestion is prevented in setting up the new connection, in cases like periodic polling of hundreds of servers.
I have a simple question. Does not it put load on the both server and client to keep the connection persistent for a long time ? Is the gain made lost??
A TCP (and hence WebSocket) connection established to a server, but not sending or receiving (sitting idle), does consume memory on the server, but no CPU cycles.
To keep the TCP connection alive (and also "responsive") on certain network environment like mobile may require periodic sending/receiving of small amounts of data. E.g. WebSocket has built-in ping/pong (non app data) messages for that. Doing so then will consume some CPU cycles, but not a lot.
Persistent connections are a tradoff.
Yes, they require the server to store the state associated with each connection, they require maintenance (such as keep-alive packets or websocket pings), and they require monitoring (to detect state changes or arriving information). So you spend some memory and CPU resources per connection.
BUT they save a lot of time, and often resources, on connection re-initializations; once established, they allow both parties to send and receive information as opposed to non-persistent client-server systems like classic HTTP.
So it really depends on the system you're building. If your system has millions of users that need connectivity to the server only once in a while, then the benefit of keeping these connections open is probably not worth the extra resources. But if you're designing something like a chat server for hundred people, then the additional responsiveness is probably worth it.

Scalability test - Connections dropped after many connections are established

I am programming with sockets (TcpListener and TcpClient actually) in C#. I wrote a server that accepts client connections and streams data to them.
In order to test scalability, I wrote a test harness that creates a certain number of connections (say 1000) in a loop, connects to the server, and writes whatever data is received to the console.
After the server receives about 1300 connections, the clients' connection attempts start failing with a regular "No connection could be made because the target machine actively refused it" exception. If the clients keep trying, some connections get through, but there are still many of them that don't. I even tried putting in delays, e.g. three simultaneous clients each opening one connection per second to the server, but the problem remains.
My guess was that the listen backlog was becoming full, but given the delays I introduced, I now doubt it. How can this behaviour be explained and solved?
Edit: before anyone else jumps on this question and marks it as duplicate without having read it...
I am using asynchronous sockets using the Asynchronous Programming Model. That's the old BeginXXX/EndXXX pattern, not the new async/await pattern. The APM uses the Thread Pool underneath, so this is not a naive one-thread-per-connection model. The connections are dormant most of the time unless I/O occurs. In that case, the .NET Framework automatically allocates threads to handle this.
Edit 2: The gist of this question, for those who thought it was too [insert silly adjective here], is: why does a server drop connections when under a heavy load? The error message I quoted usually occurs when a connection cannot be established (i.e. when you got the ip/port wrong), but this clearly isn't the case.

What is the preferred way to handle this TCP connection in C#?

I have a server application (singleton, simple .NET console application) that talks to a GlobalCache GC-100-12 for the purpose of routing IR commands. Various .NET WinForm clients on the local network connect to my server application and send ASCII commands to it. The server application queues these ASCII commands and then sends them to the GC-100-12 via a TCP connection.
My question is, what is the best way to handle this connection from the server's point of view? I can think of two ways:
Create and Open a new TcpClient for each individual request. Close the TcpClient when the request is done.
Create and Open one TcpClient when the server starts and use a keep-alive (if necessary) to keep the connection open for the lifetime of the server object.
I ask this question because I wonder about the overhead of creating a new TcpClient for each request. Is it an expensive operation? Is this a bad practice?
Currently I am doing #1, and printing the results of each transmission to the console. Occasionally some connections timeout and the command doesn't get routed, and I was wondering if that was because of the overhead of creating a new TcpConnection each time, or if it is due to something else.
I can see #2 being more complicated because if the connection does drop it has to be recreated, and that will require a bit more code to handle that circumstance.
I'm looking for any general advice on this. I don't have a lot of experience working with the TcpClient class.
We had a simillar case of opening a telnet session to an old PICK based system. We found that the cost of opening the TCP connection each time a request came in was fairly expensive, and we decided to implement a no-op routine to keep the connection open. It is more complex, but as long as your end point is not trying to serve many many clients then pinning a connection sounds like a viable solution.
You could also set it up to have a timeout, if you want to prevent keeping a connection open when there is no traffic. Five minutes of no activity then shut down the connection.

Categories

Resources