获取套接字读取操作的进度

时间:2014-07-23 15:53:50

标签: c sockets posix

我想用C编写小文件传输程序(我在Linux上工作)。 我对套接字编程很陌生,但我已经设法写了很少的服务器和 客户计划。

我的问题:

如果我有这样的话:

int read_bytes = read(socket_id, buffer, 4096);

从插座读取时,如何才能获得阅读进度? 例如,我希望每隔100ms显示已传输的字节数 至今。我非常确定我必须在这里使用线程或其他异步函数。 是否有功能,以便我可以获得number of bytes readnumber of bytes to read

更新1: 累积read()

int total_read_bytes=0, read_bytes;
char buffer[4096];
do {
    read_bytes = read(socket_id, buffer, 4096);
    total_read_bytes += read_bytes;
} while(read_bytes > 0); /* Read to end or read failed */ 

这不是非常非常低效吗? (例如,传输1MiB文件)

谢谢

2 个答案:

答案 0 :(得分:1)

如果您可以控制服务器和客户端的代码,则可以让发送方在实际发送文件之前告知接收方文件的大小。例如,使用消息中的前8个字节。这是number of bytes to read

通过在示例中累积read_bytes,您可以获得number of bytes read

答案 1 :(得分:1)

每个recv调用都将阻塞,直到它读取某些更多,但它不会(默认情况下为/ sans MSG_WAITALL)等待提供的缓冲区已满。这意味着没有必要减少缓冲区大小以便更频繁地更新总字节读取信息,您可以轻松地保留总共recv()个返回值,这些值在数据包到达时更新(或者与您的数据一样快应用程序可以从OS缓冲区处理它们。

正如您所观察到的,如果该总数每秒更新100次,您可能不希望发出100次屏幕更新,而是希望将它们限制为100ms的最小间隔。您可以使用计时器/警报来管理它,但是您有更多的边缘情况来查看计时器是否已经等待等等。使用两个线程可能更简单,其中一个周期性地检查是否需要更新:

  • 线程1:
    • while((n_bytes = recv(...))> 0)
      • total_bytes + = n_bytes;
    • 设置屏幕更新终止标志
  • 线程2:
    • last_total_bytes = -1;
    • 而屏幕更新程序终止标志未设置
      • 睡100ms
      • if last_total_bytes!= total_bytes
        • 更新屏幕
        • last_total_bytes = total_bytes

当然,您需要使用互斥或​​原子操作来协调其中的一些操作。

  

是否有一个函数,所以我可以得到...要读取的字节数?

不是来自TCP本身 - 它没有消息大小的概念,API只是确保应用程序按照发送的顺序接收字节。如果你想能够显示“到目前为止收到的N个字节,X更期望”,那么在应用程序协议级别,发送方应该在数据的前缀中加上大小 - 通常是固定宽度的二进制格式(理想情况下使用htonl或类似于recv端的send和ntohl以避免endian问题),或者使用已知的标记字符固定或与数据分离的文本表示(例如也许是NUL,空格或换行符。