调用 recv 时是否需要偏移指针?

Do I need to offset a pointer when calling recv?

在使用recv时,我总是这样做:

int len = 1000;
int n = 0;

char buf[1000];
while(n < len) {
  n += recv(socket, buf + n, len - n, 0);
}

我的逻辑是,如果 recv 没有收到 len 字节的完整数据,我应该只接收其余的字节 (len - n) 并且不应该覆盖已经存在的数据已收到(因此我将缓冲区的开头偏移到已收到内容的末尾)。每当我使用它时,它似乎都工作得很好。

但是,我看到的大多数(如果不是全部)recv 示例只是执行如下操作:

int len = 1000;
int n = 0;

char buf[1000];
while(n < len) {
  n += recv(socket, buf, len, 0);
}

如果多次调用 recv,这不会让您容易覆盖缓冲区的开头吗?

您的两个示例都没有考虑 recv() 失败的可能性。您需要检查 return 值是否有错误,例如:

char buf[1000];
int len = sizeof(buf);
int n = 0, ret;

while (n < len) {
  ret = recv(socket, buf + n, len - n, 0);
  if (ret <= 0) {
    // error handling...
    break;
  }
  n += ret;
}

当您事先确切知道需要读取多少字节并且可以预先分配一个足够大的缓冲区来容纳所有字节时,您的第一个示例非常适合使用。

当您需要更动态地流式传输数据时,您的第二个示例非常适合使用,一次 1 个缓冲区。例如,数据可能正在保存到一个文件中。或者数据太大,无法放入这么小的缓冲区,需要分块处理。或者可能将数据附加到另一个动态增长的缓冲区以供以后使用。这个用例有很多原因,例如:

char buf[1000];
int n;

while (some condition) {
  n = recv(socket, buf, sizeof(buf), 0);
  if (n <= 0) {
    // error handling...
    break;
  }
  // use buf up to n bytes...
}

一切都很糟糕。 如果我们谈论的是 C,那么 [=12=] 至少需要 space。只有当你确定一切都正确时,你才能删除它。否则你无法测试它。所有这些都意味着您不确定是否可以一次完成所有操作,因此您可能会在那里说 Transfer-Encoding: chunked。如果你不

int btx;
....
char x[9001] = {0};
int b = 0;
int e = 0;
do
{
   b = recv(btx, x + e, 9000, 0);
   e = e + b;
}while(b != 0);

和 C++

std::stringstream fbtc_b;
int btx;
....
int b = 0;
do
{
   char x[9000];
   b = recv(btx, x, 9000, 0);
   fbtc_b.write(x, b);
}while(b != 0);