I'm relatively new to C# so please bear with me. I'm working on a client server application (in C#, .NET 4.0) and I don't understand some things completely.
Let's assume that there is an established connection between a TCP server and client. Can (without errors) you write to the underlying stream from one endpoint if on the other endpoint read wasn't called yet?
If you can, how much time do you have to call read() and still get all the data? How much data can be in a buffer and how long does it stay in there if there is some sort of a buffer? Which data gets lost if you don't call read for some time (newest, oldest, ... ?)
Can there be problems if you debug both client and server application at the same time, can it happen that connection seems to be closed because one application is waiting to make a next step in debug mode?
Thank you for your precious time and answers.
Let's assume that there is an established connection between a TCP server and client. Can (without errors) you write to the underlying stream from one endpoint if on the other endpoint read wasn't called yet?
Yes. the OS has an internal buffer for each socket in it's socket implementation. Everything will be stored until that buffer is full.
If you can, how much time do you have to call read() and still get all the data? How much data can be in a buffer and how long does it stay in there if there is some sort of a buffer? Which data gets lost if you don't call read for some time (newest, oldest, ... ?)
It all depends on how large the buffer is and how often the other end point sends data to it. You can use Socket.ReceiveBufferSize to adjust it.
Can there be problems if you debug both client and server application at the same time, can it happen that connection seems to be closed because one application is waiting to make a next step in debug mode?
No. TCP connections are always open unless one of the end points closes it. Please keep in mind that other parts of your code can close the connection if you use asynchronous IO and do not break ALL threads in each application.
Related
I'm new in programing and especialy in the network world
Till now i have learned some things about tcp, sync and async programing and understand more or less how things go ( i even wrote a simple client-server program)
But there are still a few issues i couldn't find answer for them.
1. If i (client) write into a network stream (to server) but the server doesn't read the stream untill i run some command. What happens to those bits? Are they being stored somewhere on the server side until they will be read?
2. When i read the "stream" with stream.read command (c#) Where do i actually read from?
It would be nice to be directed to arelevant reading material
I thinkvit will also help me understand more async programing
Thanks
Some documentation related to the NetworkStream class:
https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.networkstream?view=netframework-4.7.2
Also, TCP provides tracking of sent packets, with validation whether the sent packets have been received. As opposed to UDP, where there is no validation whether sent packets have been received.
https://www.howtogeek.com/190014/htg-explains-what-is-the-difference-between-tcp-and-udp/
So it depends on whether it's TCP or UDP in this case.
Also, the difference between for example a FileStream and a NetworkStream in your case, is that a FileStream uses a file as a way to store information (on a hard drive, typically), where another application can read it any time, while a NetworkStream requires both applications having a connection to be active at the same time, because information is being sent/received via a cable typically. It doesn't have any persistent form of storage by default.
EDIT: Stream.Read is probably a blocking function that listens on a port until it decides to stop listening. A server needs to be listening (with Stream.Read) before it can receive information.
In the case of TCP, a server and client first need to complete a 3-way handshake before they can exchange information. https://www.inetdaemon.com/tutorials/internet/tcp/3-way_handshake.shtml
If i (client) write into a network stream (to server) but the server doesn't read the stream untill i run some command. What happens to those bits?
The data you write into stream will be passed to your OS kernel where it will be scheduled and eventually send over the network. The output queue may be filled, in this case sending function may whether wait, or refuse to send, or wait asynchronously - it depends.
After the data is sent from the client and received on the server, it is collected, assembled and checked in the kernel of the server OS. If everything's fine, the data will wait in input queue until you read it.
Are they being stored somewhere on the server side until they will be read?
So yes, your understanding is correct.
When i read the "stream" with stream.read command (c#) Where do i actually read from?
I don't know C# specifics, but let me pose it this way - on this level of abstraction, data is always read from kernel; from a piece of memory of the receiving computer. The function can wait for data to appear (optionally allowing other tasks to run in the meantime). I wouldn't expect anything low-level here. I also won't be surprised if your stream reader can buffer data or give it our in batches (e. g. readline method), but again - I don't know C# specifics.
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!
I've begun learning TCP Networking with C#. I've followed the various tutorials and looked at the example code out there and have a working TCP server and client via async connections and writes/reads. I've got file transfers working as well.
Now I'd like to be able to track the progress of the transfer (0% -> 100%) on both the server and the client. When initiating the transfer from the server to client I send the expected file size, so the client knows how many bytes to expect, so I imagine I can easily do: curCount / totalCount on the client. But I'm a bit confused about how to do this for the server.
How accurate can the server tell the transfer situation for the client? Should I guess based on the server's own status (either via the networkStream.BeginWrite() callback, or via the chunk loading from disk and networking writing)? Or should I have the client relay back to the server the client's completion?
I'd like to know this for when to close the connection, as well as be able to visually display progress. Should the server trust the client to close the connection (barring network errors/timeouts/etc)? Or can the server close the connection as soon as it's written to the stream?
There are two distinct percentages of completion here: the client's and the server's. If you consider the server to be done when it has sent the last byte, the server's percentage will always be at least as high as the client's. If you consider the server to be done when the client has processed the last byte the server's percentage will lag the one of the client. No matter what you do you will have differing values on both ends.
The values will differ by the amount of data currently queued in the various buffers between the server app and the client app. This buffer space is usually quite small. AFAIK the maximum TCP window size is by default 200ms of data transfer.
Probably, you don't need to worry about this issue at all because the progress values of both parties will be tightly tied to each other.
Should I guess based on the server's own status (either via the networkStream.BeginWrite() callback, or via the chunk loading from disk and networking writing)?
This is an adequate solution.
Or should I have the client relay back to the server the client's completion?
This would be the 2nd case I described in my 1st paragraph. Also acceptable, although not necessarily a better result and more overhead. I cannot imagine a situation right now in which I'd do it this way.
Should the server trust the client to close the connection (barring network errors/timeouts/etc)?
When one party of a TCP exchange is done sending it should shutdown the socket for sending (using Socket.Shutdown(Send)). This will cause the other party to read zero bytes and know that the transfer is done.
Before closing a socket, it should be shut down. If the Shutdown call completes without error it is guaranteed that the remote party has received all data and that the local party has received all data as well.
Or can the server close the connection as soon as it's written to the stream?
First, shut down, then close. Closing alone does not imply successful transfer.
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.
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.