首页 文章

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

提问于
浏览
2

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

对话框如下:

  • 客户端将数据发送到服务器(请求)

  • 客户端关闭套接字上的send

  • 客户端通过读取调用进行响应

  • 服务器接收数据,处理并发回响应(一次性,不分成块)

  • 服务器关闭套接字上的发送

  • 客户端收到响应,并继续处理 .

在步骤3,我使用recv()调用来阻塞和读取套接字中的数据 . 在这一点上,我想看看有多少字节的数据可用,这样我就可以分配这么多的内存 . 根据设计,已知服务器已发送所有数据,并且没有更多数据可用于发送此请求 . (见上文第5步) .

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

有没有办法检索它?

提前致谢 .

4 回答

  • 3

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

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

  • 0

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

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

  • 2

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

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

  • 1

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

相关问题