当BSD套接字报告收到RST时,如果不是所有内容都已被读取

时间:2015-06-16 09:52:48

标签: c sockets tcp

让我们想象一下从服务器发送到客户端的以下数据序列:

[data] [data] [data] [FIN] [RST]

让我们想象一下,我在客户端执行以下操作(套接字是非阻塞的):

char buf[sizeof(data)];
for (;;)
{
    rlen = recv(..., buf, sizeof(buf), ...);
    rerr = errno;
    slen = send(..., "a", 1, ...);
    serr = errno;
}

何时会看到ECONNRESET错误?

我对以下边缘情况特别好奇。让我们假设上面想象的序列的所有IP帧都已经被TCP栈接收并ACK。但是,我的客户端应用程序尚未send()recv()。第一次拨打send()是否会返回ECONNRESET?如果是这样,下一次调用recv()是否会成功并允许我在开始报告ECONNRESET之前读取其内部缓冲区中的所有内容(因为它接收到数据并拥有它)(或者返回0,因为FIN)?或者会发生不同的事情?

我将特别感谢解释这种情况的文档链接。我正在尝试使用linux tcp实现来解决这个问题,但它并不是那么清楚......

1 个答案:

答案 0 :(得分:1)

  

第一次调用send()会返回一个ECONNRESET吗?

除非它阻塞的时间足够长,以便对等方检测到断开连接的传入数据包并返回RST。大多数情况下,send只会缓冲数据并返回。

  

下一次调用recv()会成功

完全取决于(a)是否有传入要读取的内容以及(b)是否已收到RAT。

  

并允许我在开始报告ECONNRESET(或因为FIN返回0)之前读取它在内部缓冲区中的所有内容(因为它接收到数据并拥有它)?

如果收到RST,则会丢弃所有缓冲的数据。

这一切完全取决于两端缓冲区的时间和大小。