C 中 send() 的最大 size_t 值

max size_t value on send() in C

我正在用 C 编写一个 tcp 服务器,但我在发送时遇到了问题。我读取本地文件并将数据发送回客户端,当文件很小时我没有问题,但是当它变大时我有这种奇怪的情况:

服务器 tcp:

 // create socket, bind, listen accept

// read file
fseek(fptr, 0, SEEK_SET);
// malloc for the sending buffer
ssize_t read = fread(sbuf, 1, file_size, fptr);

while(to_send>0) {
  sent = send(socket, sbuf, buf_size, 0);
  sbuf += sent;
  to_send -= sent;
}

在发送的大文件变得等于 size_t 的最大值时,我认为我有缓冲区溢出。我怎样才能防止这种情况发生?从文件中读取并将其发回的最佳做法是什么?

问题是您每次发送 buf_size 个字节,即使没有那么多了。

例如,假装 buf_size 是 8,而您要发送 10 个字节(所以最初,to_send 也是 10)。第一个send发送8个字节,所以需要再发送2个。第二次,您还发送了 8 个字节(这可能是越界读取)。然后,to_send 将为 -6,与 SIZE_MAX - 5.

相同

简单的解决方法是发送 to_send 如果它更小:

sent = send(socket, sbuf, to_send < buf_size ? to_send : buf_size, 0);

另外,send returns -1 如果不成功。这与 SIZE_MAX 分配给 size_t 时相同。你需要一些错误处理来解决这个问题。

On huge files sent becomes equals to the max value of size_t, I think that I have a buffer overflow.

因为sent得到的值是send()的return值,而send()returnsssize_t,这是一个有符号类型不太可能比 size_t 宽,实际上可以肯定的是 send() 通过 returning -1 指示错误。在这种情况下,它还会将 errno 设置为指示错误的值。在我曾经接触过的任何系统上,它都不能 return size_t 的最大值。

How can I prevent this?

首先,在你担心预防它之前,你应该确保检测

  1. sent 声明为 ssize_t 以匹配 send() 的 return 类型,而不是 size_t
  2. 检查值 return 进入 sent 是否存在此类错误情况。

其次,如果您确实处理的文件长度超过了 ssize_t 可以表示的长度(更不用说 size_t),那么将整个文件加载到内存中是个糟糕的主意在发送任何内容之前。相反,将其加载到(小得多的)块中,并一次发送一个这样的块。这不仅会降低感知延迟,而且还会避免与接近所涉及数据类型的限制相关的任何风险。

此外,当您这样做时,请注意正确操作。您已经很好地将 send() 调用包装在一个循环中以说明短写,但正如@Artyer 在他的回答中所描述的那样,您不太正确,因为您没有减少尝试的字节数发送第二次和后续呼叫。

What is the best practice to read from a file and send it back?

同上