如果应用程序能确保套接字的发送缓冲区始终有空间,那么阻塞和非阻塞发送是否具有相同的性能?在这种情况下,两种方法是否有任何优势?
send
之间的唯一区别是内核是否将进程置于休眠状态或返回EWOULDBLOCK
。因此,就性能而言,不应该有任何区别。EWOULDBLOCK
而不是等待(比如)交换操作。new_segment:
if (!sk_stream_memory_free(sk))
goto wait_for_sndbuf;
skb = sk_stream_alloc_skb(sk, 0, sk->sk_allocation);
if (!skb)
goto wait_for_memory;
sk_stream_wait_memory
并使用取决于是否为非阻塞发送的timeo
值。该函数又会根据timeo
将进程置于睡眠状态或返回EAGAIN
。send
之间是否有任何差异-性能或其他方面?”SO_SNDBUF
套接字选项,您可以知道套接字具有足够的可用空间。在这种情况下,阻塞式send
与非阻塞式send
是否会表现不同?send
不能永远阻塞。这与使用足够的可用虚拟内存调用calloc
的方式相同,不能永远阻塞。最终,系统将找到发送数据所需的资源。send
可能会永远阻塞,具体取决于套接字接收端正在发生什么。)然而,即使发送缓冲区有足够的空间,非阻塞式send
仍然可能返回EWOULDBLOCK
。因此,如果您使用非阻塞式套接字,则您的代码必须处理这个问题,无论您对发送缓冲区或其他任何事情了解多少。请记住,您不能总是确定您的发送将被快速执行。
例如,如果另一端的套接字未使用recv进行读取,则您的缓冲区将会满。
当然,如果您编写应用程序的两个方面并始终进行读取,则在性能方面不会有显着差异。
确保套接字发送缓冲区始终有空间的唯一方法是在缓冲区已满时不进行发送。
您确实可以确定发送缓冲区是否有空间 - 在某些系统上。如果在阻塞模式下没有空间,则可以选择可写性 - 在某些系统上。在其他系统上,您无法确定是否有空间和/或无法在阻塞模式下进行选择(select())。
在这种系统上,您没有任何好的实现选择,除了发送并阻塞,或者使用阻塞模式。
在您可以知道但无法选择(select())的系统上,您可以循环和休眠,但您无法知道要休眠多长时间,因此您将会浪费时间睡得太久,与阻塞相比,阻塞会准确地阻塞正确长度的时间。
SO_SNDBUF
套接字选项,你可以知道它有多少可用空间。即使在这种情况下,当系统处于内存压力下时,阻塞和非阻塞套接字的行为也可能不同。 - Nemo