Where are network stream stored - c#

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.

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!

Keeping track of a file transfer percentage

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.

TCP Socket buffer and Data Overflow

My application is acting as client for a banks server, sending request and getting response from that server. After response processing is done in database which takes some time, so If sever send response in 0.5 second and db operation takes 1 sec after which only my application again try to receive data from server through begin receive then should data will be accumulated somewhere and if yes where it will be stored. Is there will be some limitation so that data will be overflowed and if it happen whether it will closed this socket. I am declaring my socket buffer size to 1024. If anyone also have some article which clear my doubts please share it.
Can you control what the server is sending to you? In most cases when the receiver operates on the received data, sending an application-level ACK upon finishing the work will allow the sender to know when to send the next request. This will ensure no data is lost (since TCP will make sure it does not get lost in the network).
If you can't change the way the server sends you data, you can consider running the receiver in a different thread, where it will save every incoming request to a cache (either only in RAM or to the HD). Then, a worker thread (or multiple threads) will read requests from that cache and do the work you need. This way you will have full control of the buffering of the data.
I think you will read the data in chunks yourself with the Socket - don't you? Than just don't read more than you can handle. The sender should do the same - if your input-buffer overflows the sender should wait before sending more. But maybe there will be an error in this case. If this is really a big issue just start by downloading the data into a file on your disk and process the data after you got all of it. I don't think your HDD will be slower than your network :)

Client Server (TCP) Question (Time)

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.

Async Sockets example which shows passing an object?

I need to create a server process which can push high frequency data (1000 updates per second) to around 50 client. I'm thinking the best way you do this is using async sockets with the SocketAsyncEventArgs type.
The client -> server connections will be long running at least several days to indefinite. I plan to have a server process listening and the clients connect and the server starts pushing the data to the clients.
Can someone point me to or show me an example of how to do this? I can't find any example showing a server process pushing an object to a client.
EDIT: This is over a gigibit LAN. Using windows server with 16 cores and 24gb ram
thanks
First, some more requirements from your side is required. You have server with lots of muscle, but it will fail miserably if you don't do what has to be done.
can the client live without some of the data? I mean, does the stream of the data need to reach other side in proper order, without any drops?
how big is 'the data'? few bytes or?
fact: scheduling interval on windows is 10 msec.
fact: no matter WHEN you send, clients will receive it depending on lots of stuff - network config, number of routers in-between, client processor load, and so on. so you need some kind of timestamping here
Depending on all this, you could design a priority queue with one thread servicing it and sending out UDP datagrams for each client. Also, since (4) is in effect, you can 'clump' some of your data together and have 10 updates per second of 100 data.
If you want to achieve something else, then LAN will be required here with lots of quality network equipment.
If you want to use .NET Sockets to create this server-client project, then this is a good outline of what's needed:
Since the server will be transferring data to several clients simultaneously, you'll need to use the asynchronous Socket.Beginxxx methods or the SocketAsyncEventArgs class.
You'll have clients connect to your server. The server will accept those connections and then add the newly connected client to an internal clients list.
You'll have a thread running within the server, that periodically sends notifications to all sockets in the clients list. If any exceptions/errors occurs while sending data to a socket, then that client is removed from the list.
You'll have to make sure that access to the clients list is synchronized since the server is a multithreaded application.
You don't need to worry about buffering your send data since the TCP stack takes care of that. If you do not want to buffer your data at all (i.e. have the socket send data immediately), then set Socket.NoDelay to true.
It doesn't seem like you need any data from your clients, but if you do, you'd have to make sure your server has a Socket.BeginReceive loop if using Socket.BeginXXX pattern or Socket.ReceiveAsync method if using SocketAsyncEventArgs.
Once you have the connection and transmission of data between server and client going, you then need to worry about serialization and deserialization of objects between client and server.
Serialization which occurs on the server is easy, since you can use the BinaryFormatter or other encoders to encode your object and dump the data onto the socket.
Deserialization on the other hand, which occurs on the client, can be pretty complex because an object can span multiple packets and you can have multiple objects in one packet. You essentially need a way to identify the beginning and end of an object within the stream, so that you can pluck out the object data and deserialize it.
One way to do this is to embed your data in a well known protocol, like HTTP, and send it using that format. Unfortunately, this also means you'd have to write a HTTP parser at the client. Not an easy task.
Another way is to leverage an existing encoding scheme like Google's protocol buffers. This approach would require learning how to use the protocol buffers stack.
You can also embed the data in an XML structure and then have a stream-to-XML decoder on your client side. This is probably the easiest approach but the least efficient.
As you can see, this is not an easy project, but you can get started with the Socket.BeginSend examples here and here, and the SocketAsyncEventArgs example here
Other Tips:
You can improve the reliability of your communication by having the client maintain two connections to the server for redundancy purposes. The reason being that TCP connections take a while to establish, so if one fails, you can still receive data from the other one while the client attempts to reconnect the failed connection.
You can look into using TCPClient class for the client implementation, since it's mostly reading a stream from a network connection.
What about rendezvous or 29 west? It would save reinventing the wheel. Dunno about amqp or zeromq they might work fine too....

Categories

Resources