当前位置: 首页 > 知识库问答 >
问题:

tcp套接字recv是否会在recv buf已经有数据时返回“资源暂时不可用”

焦驰
2023-03-14

我使用tcpdump从客户端捕获数据包,每个数据包都是分段到最大1448字节的数据,但是head只有5字节,为什么我可以成功读取head,但是下面的data recv()操作又会返回ee?当数据已经到达recv缓冲区时,recv是否可能返回EAGAIN?在我看来,我可以读取前5个字节,所以必须有更多的数据在recv缓冲区读取。

可能与TCP/IP协议栈中的组装过程有关。代码如下所示,每个pdu recv,需要10次或更多的重试,也许成功。

...
#define HDR_LEN    5
n = epoll(epfd, events, 1000, -1)
for(i =0; i < n; i++)
{
    uint8 pHdr[HDR_LEN] = {0};
    uint16 pdulen = 0, offset =0;
    infd = events[i].fd;
    nRead = recv(infd, pHdr, HDR_LEN);   // read the data head first
    pdulen = ntohs(*(uint16 *)(pHdr+2));   // get the pdu len from the head
    uint8 *pbuf = malloc(pdulen+HDR_LEN);

    memcpy(pbuf, pHdr, HDR_LEN);            // move the head to buf
    while(offset != pdulen)                 // then read the pdu data
    {
        nRead = recv(infd, pbuf+HDR_LEN+offset, pdulen-offset);
        if (nRead <=0)
        {
            if (nRead == -1 && errno == EAGAIN) // resource temporarily unavailable 
            {
                if (retry < 5)
                {
                    usleep(500);
                    retry++;
                    continue;
                }
                else
                     break;  // already try 5 times, should always continue?
            }
            else
                break;
        }
        else
        {
             offset += nRead;
             retry = 0;
        }
    }
    if (offset == pdulen)
        process(pbuf, pdulen+HDR_LEN); // process the complete data
    ...
}
...

共有1个答案

牛凌
2023-03-14

epoll将告诉您是否可以recv而不阻塞。如果recv使用了套接字的所有数据,那么下一个recv将阻塞,直到有更多的数据,或者返回EAGAIN(如果非阻塞套接字)。

一个常见的模式是:

  1. 使用select/poll/epoll检测何时可以读取套接字。
  2. 在就绪套接字上调用recv一次,并将接收到的数据追加到缓冲区。
  3. 检查缓冲区是否包含足够的数据进行处理。如果是,则进行处理。否则,让选择/poll/epoll告诉您何时可以阅读更多内容。
 类似资料:
  • 我正在实现一个UNIX域套接字进程间通信代码,在试图从套接字读取时,我随机地碰到了这个错误--“errno 11:资源暂时不可用”。我使用MSG_PEEK从套接字读取字节数,并为接收缓冲区分配字节数,并读取实际数据。 套接字是一个阻塞套接字,我没有任何非阻塞的代码(总之,接受/读/写)。在阻塞套接字读取中,有什么可能导致这种情况的指针吗?在MSG_PEEK的手册页中,当socket标记为非阻塞时,

  • 创建套接字 使其非阻塞 呼叫连接 按预期返回-1和errno EINPROGRESS 调用select 返回>0,因此已建立连接 再次阻塞套接字 此部件的代码如下: 那还行。但是我有一个循环,在这个循环中我调用了一个函数,该函数检查是否收到了要读取的新数据包:

  • 我正在编写一个简单的TCP客户端和服务器Perl脚本。到现在为止,我使用wireshark验证了三路TCP握手,并且建立了连接。但当我尝试发送或恢复数据时,什么也不会发生。 1)客户端和服务器之间的主要区别只是服务器增加了一个LISTEN参数,使它能够侦听传入的连接? 2)在recv和显示数据之间是否缺少任何步骤? 3)当程序第一次执行while循环时,难道不应该至少发送硬编码字符串“$respo

  • 我正在使用TCP/IP套接字,我已经读过函数。因此,每当对等体断开连接时,recv按照文档返回0,但在windows上它不返回零,而是返回-1,并且中的值是我无法理解它为什么这样做。同样的代码在Linux中运行得非常好。

  • 我想用pywebkitgtk捕获网页。我已经在那台机器上安装了X org服务器,除了一些例外情况外,还启动了X服务器,但是X服务器正在运行。问题是我不能从X unix套接字中读取任何数据,它是path=@“/tmp/.x11-unix/x0”的PF_FILE类型,recvfrom正在抛出EAGAIN(资源暂时不可用)错误,对该套接字的轮询经常超时,没有任何数据,下面是跟踪日志,在其中我们可以找到成