获取可在套接字中读取的字节数

时间:2012-02-02 07:26:49

标签: c++ sockets recv peek

这是我的情景。我有一个与服务器通信的TCP客户端。服务器和客户端都在本地计算机上运行(Windows)。

对话框如下:

  1. 客户端将数据发送到服务器(请求)
  2. 客户端关闭套接字上的发送
  3. 客户端通过读取响应呼叫阻止
  4. 服务器接收数据,处理并发回响应(一次性,不分成块)
  5. 服务器关闭套接字上的发送
  6. 客户收到回复,然后继续处理。
  7. 在第3步,我使用recv()调用来阻塞并从套接字读取数据。在这一点上,我想看看有多少字节的数据可用,这样我就可以分配这么多的内存。 根据设计,已知服务器已发送所有数据,并且没有更多数据可用于发送此请求。 (见上文第5步)。

    我尝试过使用MSG_PEEK选项的recv(),但这似乎没有给出可用的总字节数。

    有没有办法检索它?

    提前致谢。

4 个答案:

答案 0 :(得分:3)

在没有预先分配或重新分配缓冲区的情况下,这样做的一种方法是:(a)发送发送方正在发送的字节数(例如,以网络字节顺序的四字节int),(b) )让接收器接收这四个字节并分配接收缓冲器,然后(c)让接收器发送先前发送长度的实际数据。请注意,(c)发送者可以在没有接收到关于(a)来自接收者的反馈或回复的情况下发生。

我一直在尝试使用fstat来获取套接字上可用的数据量,但它似乎不是可移植的。在Mac系统上,它适用于我的应用程序。在Linux系统上,它没有。

答案 1 :(得分:2)

使用TCP无法知道有多少字节。请记住,TCP是一种“流式”协议,在连接关闭之前,有一个流的开始但没有结束。

您可以做的是将小块读入缓冲区,并在需要时放大缓冲区。

答案 2 :(得分:1)

至少在Windows上,您可以使用ioctlsocket()FIONREAD命令来确定recv()可以无阻塞地读取的当前字节数。当你实际调用recv()时,可能会有更多字节到达。

正如@LokiAstari所说,你应该在一个循环中调用recv(),直到它返回0个字节来指示套接字已经关闭。您不需要知道可用的字节数,每次只传递一个固定长度的缓冲区,recv()将返回实际读取的字节数。将每个非零长度缓冲区读取附加到另一个缓冲区,该缓冲区根据需要增长,直到您收到所有数据,然后在准备好后处理第二个缓冲区。

答案 3 :(得分:0)

它部分取决于响应的大小,因为即使将其作为一个块发送,底层传输也可能将其分解为块。例如,以太网的最大包大小为1500字节。虽然您只发送一次,但很可能您将同时收到所有内容,但如果您使用的是TCP,则无法保证,因为它是面向流的。如果使用UDP,则更有可能以单个数据包的形式接收响应。