2012-02-02 55 views
2

这是我的场景。我有一个与服务器交谈的TCP客户端。服务器和客户端都在本地计算机上运行(Windows)。获取套接字中可读取的字节数

对话框云一样的东西:

  1. 客户端将数据发送到服务器(请求)
  2. 客户端通过读取调用
  3. 客户端块不关机发送插座上响应
  4. 服务器接收该数据,处理和发送回的响应(一个镜头,不破碎成块)
  5. 服务器确实关闭用于发送在插座上
  6. 客户端收到响应,并继续处理。

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

我试图与MSG_PEEK选项的recv(),但似乎并没有给可用的字节总数。

有没有办法检索它?

在此先感谢。

+5

仅仅因为服务器已经发送了所有的数据,这并不意味着它将全部到达同一时间。仅仅因为recv()返回并不意味着你拥有了一切。你应该继续调用recv()直到in,表示没有任何东西返回0 – 2012-02-02 07:31:23

+0

我在这里讲的是无知,但我怀疑答案是否定的,因为内核无法知道字节总数,直到它有收到所有的数据包。直到客户询问后才可能发生这种情况。所以你可以希望的最好是一个下限,这是MSG_PEEK给你的。 – 2012-02-02 07:33:56

回答

2

使用TCP无法知道有多少字节。请记住,TCP是一个“流式传输”协议,有一个流的开始,但直到连接关闭才结束。

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

+0

如果缓冲区的大小大于可用字节的大小,那么我们试图读取比套接字提供的更多的字节。 – 2012-08-23 05:05:37

+0

@sumitdhyani然后你会得到可用的东西,除非你在'MSG_WAITALL'中使用'recv',在这种情况下,调用将被阻塞,直到系统收到足够的数据来满足你的请求。 – 2012-08-23 05:41:48

1

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

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

3

的一种方法是:(1)发送的字节数的发送者发送(例如,作为四个字节整型,以网络字节顺序),( b)让接收器接收这四个字节并分配一个接收缓冲器,然后(c)让接收器发送先前发送长度的实际数据。请注意,(c)可能由发件人发生而未收到有关(a)接收方的反馈或答复。

我一直在试图用FSTAT获取套接字上可用的数据量,但不会出现移植。在Mac系统上,它适用于我的应用程序。在Linux系统上,它没有。

0

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