c - 当连接打开但没有发送数据时,send() 和 recv() 返回什么?

标签 c sockets

我想接收以多个 block 发送的请求。为此,我使用带有接收功能的 TCP 套接字。我按如下方式循环接收:

while ((total_recv < MAX_HEADER) && (received = recv(client, req_buffer, CHUNK, 0)) > 0) {
total_recv += received;
if (strstr(req_buffer, delimiter) != NULL)
    break;
}

我的目标是当我收到末尾由分隔符标记的 header 时停止接收。我不能保证分隔符存在,因此如果total_recv 大于或等于最大已知 header 大小,我会中断循环。

我不喜欢这样。令我困扰的是我可以收到一个没有分隔符且小于最大 header 大小的数据包。在这种情况下,我必须假设recv将继续增加total_recv直到循环中断。从读取套接字 API 中我知道,recv 将返回读入缓冲区的字节数,如果出现错误,则返回 -1;如果连接已关闭,则返回 0。

是否有更好的方法在不依赖超时的情况下循环接收?当连接打开但发送方或接收方没有传输数据时,send() 和 recv() 到底返回什么?

最佳答案

如果套接字处于阻塞模式(默认),recv() 将等待,直到有数据可返回。处理这个问题的唯一方法是超时。最简单的方法是使用 select()epoll()

如果套接字处于非阻塞模式,如果没有可用的内容,recv()将立即返回-1,并且errno将设置为 EWOULDBLOCK。您仍然需要使用某种超时,因为发生这种情况的原因仅仅是您在收到所有已发送的数据之前过早调用 recv()

超时是一种非常脆弱的机制,因为总是可能出现持续时间超过超时时间的临时网络错误,并且您会错误地将中断之前的数据视为完整的数据。

也许你可以重新设计协议(protocol)来更好地处理这个问题。不要读取直到分隔符,而是让发送者发送包含消息中字节数的前缀,然后调用 recv() 直到获得那么多字节。

关于c - 当连接打开但没有发送数据时,send() 和 recv() 返回什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57777398/

相关文章:

C# TCP 套接字编程 - 确定连接是否已断开

c - 使用非阻塞套接字获取 SIGPIPE——这正常吗?

具有单写入器、多个读取器的 Linux IPC

C程序在接受用户输入之前退出

c - 带方括号的 Typedef 声明

c - 删除C中链表的第一个元素

C 代码在函数调用后声明预期的变量类型

复制结构体数组元素中的字符串

C# TCP Socket编程——向所有套接字发送数据

c++ - 同一台计算机上的 UDP 连接。 1 个服务器。多个客户端