In short when the server can handle only 1k per second, the client will not get the opportunity to send 1M per second. And this for 2 reasons :
- TCP has a slow start mechanism
- TCP has a window mechanism where each side of the TCP connection is constantly advertising its own ability to receive to the other side.
It would not make sense for the client to send data for more than the advertised window size because the server is going to drop any segments that are outside its window size in the first place so the client would have to resend if it were to ignore the window size.
Buffers are in place in different layers. The buffers you can set via socket options are socket level buffers, they don't have direct control over the TCP window size. If you don't set these buffers you get default buffers sizes at the socket level. TCP is queueing depending on whether out of order packets that are in the window size are received. If it receives data that is in order, it triggers the socket level and only then the data is pushed into the socket level buffers and then only for the amount that there is space available.
If TCP is not able to push all the data that it has received on the socket buffer, then this will have influence on the algorithm that calculates the TCP window size. This calculation mechanism is based on the amount of bytes that are left in the TCP buffers.
Nobody will crash, neither the server and nor the client.
At the client side, the one that could send at high speeds, similar things happen because TCP will see based on the advertised window size of the server that it cannot put much data on the wire. So the clients send buffer will fill up. If it is full, the client socket will either block in send (blocking mode) or return an error indication that it would block (non blocking mode).
So this does not just say what happens , but I have also tried to explain why those things happen and how it is implemented.