C++ 套接字编程 TCP/IP 套接字缓冲区的最大大小?

2021-12-11 00:00:00 sockets buffer c++ tcpclient tcpserver

我正在使用 C++ TCP/IP 套接字.根据我的要求,我的客户端必须连接到服务器并读取它发送的消息(这真的很新,不是吗)但是......在我的应用程序中,我必须等待一段时间(通常为 1 - 2 小时)) 在我真正开始阅读消息之前(通过 recv() 或 read())并且服务器仍然继续发送消息.

I am using C++ TCP/IP sockets. According to my requirements my client has to connect to a server and read the messages sent by it (that's something really new, isn't it) but... in my application I have to wait for some time (typically 1 - 2 hrs) before I actually start reading messages (through recv() or read()) and the server still keeps on sending messages.

我想知道缓冲区的容量是否有限制,用于保存这些消息以防它们不被读取,以及使用谁的物理内存来缓冲这些消息?发件人还是收件人?

I want to know whether there is a limit on the capacity of the buffer which keeps those messages in case they are not read and whose physical memory is used to buffer those messages? Sender's or receiver's?

推荐答案

TCP 数据在发送方和接收方都被缓冲.接收方的socket接收缓冲区的大小决定了在没有确认的情况下可以传输多少数据,发送方的发送缓冲区的大小决定了在发送方阻塞或获得EAGAIN/EWOULDBLOCK之前可以发送多少数据,取决于阻塞/非阻塞模式.您可以将这些套接字缓冲区设置为您喜欢的大小,最大为 2^32-1 字节,但是如果您将客户端接收缓冲区设置为高于 2^16-1,则必须在连接套接字之前这样做,以便 TCP 窗口缩放可以在连接握手中协商,以便高 16 位可以发挥作用.[服务器接收缓冲区在这里不相关,但如果您将其设置为 >= 64k,则需要将其设置在侦听套接字上,从那里它将被接受的套接字继承,再次握手可以协商窗口缩放.]

TCP data is buffered at both sender and receiver. The size of the receiver's socket receive buffer determines how much data can be in flight without acknowledgement, and the size of the sender's send buffer determines how much data can be sent before the sender blocks or gets EAGAIN/EWOULDBLOCK, depending on blocking/non-blocking mode. You can set these socket buffers as large as you like up to 2^32-1 bytes, but if you set the client receive buffer higher than 2^16-1 you must do so before connecting the socket, so that TCP window scaling can be negotiated in the connect handshake, so that the upper 16 bits can come into play. [The server receive buffer isn't relevant here, but if you set it >= 64k you need to set it on the listening socket, from where it will be inherited by accepted sockets, again so the handshake can negotiate window scaling.]

然而,我完全同意 Martin James 的观点,即这是一个愚蠢的要求.它在服务器上浪费一个线程、一个线程堆栈、一个套接字、一个大套接字发送缓冲区、一个 FD 和所有其他相关资源两个小时,并可能影响其他线程,从而影响其他客户端.它还错误地给服务器一个印象,认为已经接收了两个小时的数据,而实际上它只是传输到接收缓冲区,这可能会导致恢复情况下的未知并发症:例如,服务器可能无法重建之前发送的数据.您最好在准备好开始接收数据之前不要连接,否则在客户端读取数据并将其假脱机给自己以备后用.

However I agree entirely with Martin James that this is a silly requirement. It wastes a thread, a thread stack, a socket, a large socket send buffer, an FD, and all the other associated resources at the server for two hours, and possibly affects other threads and therefore other clients. It also falsely gives the server the impression that two hours' worth of data has been received, when it has really only been transmitted to the receive buffer, which may lead to unknown complications in recovery situations: for example, the server may be unable to reconstruct the data sent so far ahead. You would be better off not connecting until you are ready to start receiving the data, or else reading and spooling the data to yourself at the client for processing later.

相关文章