2

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

对话框类似于:

  1. 客户端向服务器发送数据(请求)
  2. 客户端确实关闭以在套接字上发送
  3. 客户端通过读取响应阻塞
  4. 服务器接收数据、处理并发回响应(一次性,不分成块)
  5. 服务器确实关闭以在套接字上发送
  6. 客户端收到响应,并继续处理。

在第 3 步,我正在使用 recv() 调用来阻止并从套接字读取数据。此时,我想偷看一下有多少字节的数据可用,这样我就可以分配这么多的内存。通过设计,知道服务器已经发送了所有数据,并且没有更多的数据可以发送这个请求。(参见上面的步骤 5)。

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

有没有办法找回它?

提前致谢。

4

4 回答 4

3

至少在 Windows 上,您可以使用ioctlsocket()FIONREAD命令来确定当前可用于recv()读取而不阻塞的字节数。但是,当您实际调用 时recv(),可能已经到达了更多字节。

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

于 2012-02-02T21:21:34.533 回答
3

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

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

于 2012-11-14T15:37:45.323 回答
2

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

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

于 2012-02-02T07:29:59.440 回答
0

它部分取决于响应的大小,因为即使将其作为一个块发送,底层传输也可能将其分成块。例如,以太网的最大数据包大小为 1500 字节。尽管您将所有信息都发送一次,但您可能会一次收到所有信息,但不能保证您是否使用 TCP,因为它是面向流的。如果您使用 UDP,则更有可能以单个数据包的形式接收响应。

于 2013-05-22T22:14:32.163 回答