首页 文章

如何判断套接字recv()函数在返回值0时收到了多少数据?

提问于
浏览
1

这似乎是一个愚蠢的问题,但它一直让我疯狂 . 我正在进行网络编程分配,我编写的代码的一部分是使用缓冲区,缓冲区长度和为标志指定的零调用套接字recv()函数 . recv()调用返回零值,并且手册页显示返回值为零表示“流套接字对等已执行有序关闭” .

问题是recv()调用实际上确实接收了数据,并且确实更新了我的缓冲区 . 我知道因为我可以使用printf将其打印出来,并且我希望在recv()调用期间收到的数据显示在printf输出中 . 但问题是,由于recv()返回零,我真的不知道实际上有多少数据放入我的缓冲区 . 我在缓冲区上做了一个memset,在我使用它之前将其归零,所以我想我之后可以对缓冲区执行strlen()调用,但这看起来像是一个黑客 . 这是我想要做的吗?

另一件事是套接字仍然是打开的,因为我在第一次recv()调用后不久在while循环中循环遍历套接字并继续接收更多数据 . 我正在使用的缓冲区的大小是char缓冲区[4096]数组 . 任何见解将不胜感激 .

4 回答

  • 1

    由于您没有提供代码,我无法确切说明您的问题在哪里 . 但如果你这样做,它应该按预期工作:

    ssize_t bytes_read = 0;
    
        while ((bytes_read = recv(sock_fd, buffer, sizeof buffer, 0)) > 0) {
            printf("Bytes received: \t%zd\n", bytes_read);
            // ...
        }
    

    在这里你可以看到 recv() 在返回 0 或负值后不再被调用 .

    此外,我不会使用 memset() 在每次迭代时将缓冲区清零,这是低效的,只是浪费了周期 . 而是读取 bytes_readrecv() 返回的 buffer 的字节数 .

    我可以看到,Remy Lebeau也已经指出了一些额外的细节 .

  • 1

    手册页说返回值为零表示'流套接字对等已执行有序关闭' .

    不仅如此,它还意味着您在获得此零之前已收到对等方发送的所有数据 .

    问题是recv()调用实际上确实接收了数据,并且确实更新了我的缓冲区 .

    不,没有 .

    我知道因为我可以使用printf将其打印出来,并且我希望在recv()调用期间收到的数据显示在printf输出中 .

    它已经存在了 .

    问题是,因为recv()返回零,我真的不知道实际上有多少数据放入我的缓冲区 .

    没有数据放入缓冲区 . 它没有受到任何干扰 . 传输的字节数为零 . 这是它的意思 .

    我在缓冲区上做了一个memset,在我使用它之前将其归零

    不要这样做 . 这是货物崇拜节目 . 没有必要以任何方式 . 这只是更多的代码,更多的时间,更多的空间,都浪费了 .

    ,所以我想我之后可以在缓冲区上执行strlen()调用,但这看起来像是一个黑客 . 这是我想要做的吗?

    不.TCP已经提供了返回值,并且它也不排除具有内部空字节的数据 . 这里有更多的货物崇拜节目 .

    另一件事是插座仍然打开

    正确 . 它一直打开,直到你关闭它 .

    因为我在第一次recv()调用后不久在while循环中循环遍历套接字并继续接收更多数据 .

    不可能,抱歉 .

    我喜欢@ RemyLebeau的建议,你已经通过零长度作为解释 .

  • 2

    问题是recv()调用实际上确实接收了数据,并且确实更新了我的缓冲区 . 我知道因为我可以使用printf将其打印出来,并且我希望在recv()调用期间收到的数据显示在printf输出中 . 但问题是,由于recv()返回零,我真的不知道实际上有多少数据放入我的缓冲区 .

    这根本不可能 . recv() 可以:

    • 接收1个或多个字节并返回一个正值,指定接收的字节数 .

    • 正常关闭时返回0,没有收到数据 .

    • 如果请求0字节则返回0 .
      错误时

    • 返回-1 .

    这就对了 . recv() 无法接收某些数据但返回0.它无法正常工作 . 它是一个或另一个 .

    另一件事是套接字仍处于打开状态,因为我在第一次recv()调用后不久在while循环中循环遍历套接字并继续接收更多数据 .

    可能发生的 only 方式是,如果第一个 recv() 返回0,因为请求了0个字节,而不是因为发生了关闭 . 如果发生了真正的关闭, all 后续读取将不再接收任何数据 . 他们不能 . 通过接收 FIN 数据包发出正常关闭信号,这意味着将不再发送数据 . 发送 FIN 后,发件人's socket stack won' t将允许发送更多数据 . 这是TCP工作方式的一部分 .

    你的代码中明显有一个错误(你没有显示) . 有时,您必须将缓冲区大小0传递给 recv() ,导致它返回0.这是后续读取在给定非零缓冲区大小时仍然可以接收更多数据的唯一方法 .

  • 3

    哦,我的天啊 . 我发现问题是什么,这是一个非常基本的错误 . 确保在if语句中检查括号的顺序 . 以下是出错的代码 .

    如果你看,你可以在最右边看到两个右括号 . 在小于号的前面应该有两个右括号,在最右边有一个右括号 .

    我发现这是因为我在拍摄截图后编辑了我的回复,并在我提交之前不久查看我编辑过的问题时注意到了这一点 . 这就是当你在前一天晚上2:30睡觉前6小时处理代码时会发生的事情 .

    再次感谢大家,并保重 .

相关问题