send() 和 write() 到已满的 TCP 输出缓冲区,不要阻塞

send() and write() to TCP output buffer which is full don't block

我遇到一个简单函数(语言是 C++)的问题,该函数遍历对象列表,序列化它们并将它们发送到远程服务器。我在运行 FreeRTOS 和 LwIP 的 ESP32 板上 运行 这个函数,所以我有一个默认限制为 5744 字节的 TCP 输出缓冲区(我可以自定义它,但我不想超过 10- 15000 字节)。

基本上是这样发生的:我在套接字上多次调用(通常 200-300 次)write() 或 send(),每次写入约 1400 个字节。一段时间后,如果另一端的服务器有点慢,我就会使 TCP 输出缓冲区饱和。 现在,根据我的理解,send() 或 write() 应该等到有一些 space 再次将数据写入套接字,而不是函数立即 returns 一个不同于值 I 的值想写(假设 1400 字节)。

char buffer[1460];
result = write(current_socket, buffer, 1460);
if(result != 1460){
    // error
} else {
    // everything ok
}

该套接字是默认套接字,因此它是一个阻塞套接字,未指定任何选项。我希望写入阻塞,直到有足够的 space 来写入上面代码中指定的所有 1460 个字节。写入应该 return 错误的唯一原因应该是另一端的失败,例如服务器关闭套接字。这可能吗?

您所看到的称为部分写入。这对于 TCP 来说是正常的。

当缓冲区部分满时,调用 write 复制适合的数据,returns 复制到缓冲区的字节数。稍后处理剩余数据是您的工作。

为了发送您的数据缓冲区,您需要循环直到缓冲区为空:

buf_ptr = 0;
buf_end = 1460;
while(buf_ptr < buf_end) {
    rc = write(fd, buf + buf_ptr, buf_end - buf_ptr);
    if(rc <= 0)
        break
    buf_ptr += rc;
}