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?
首先,在你担心预防它之前,你应该确保检测它
- 将
sent
声明为 ssize_t
以匹配 send()
的 return 类型,而不是 size_t
和
- 检查值 return 进入
sent
是否存在此类错误情况。
其次,如果您确实处理的文件长度超过了 ssize_t
可以表示的长度(更不用说 size_t
),那么将整个文件加载到内存中是个糟糕的主意在发送任何内容之前。相反,将其加载到(小得多的)块中,并一次发送一个这样的块。这不仅会降低感知延迟,而且还会避免与接近所涉及数据类型的限制相关的任何风险。
此外,当您这样做时,请注意正确操作。您已经很好地将 send()
调用包装在一个循环中以说明短写,但正如@Artyer 在他的回答中所描述的那样,您不太正确,因为您没有减少尝试的字节数发送第二次和后续呼叫。
What is the
best practice to read from a file and send it back?
同上
我正在用 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?
首先,在你担心预防它之前,你应该确保检测它
- 将
sent
声明为ssize_t
以匹配send()
的 return 类型,而不是size_t
和 - 检查值 return 进入
sent
是否存在此类错误情况。
其次,如果您确实处理的文件长度超过了 ssize_t
可以表示的长度(更不用说 size_t
),那么将整个文件加载到内存中是个糟糕的主意在发送任何内容之前。相反,将其加载到(小得多的)块中,并一次发送一个这样的块。这不仅会降低感知延迟,而且还会避免与接近所涉及数据类型的限制相关的任何风险。
此外,当您这样做时,请注意正确操作。您已经很好地将 send()
调用包装在一个循环中以说明短写,但正如@Artyer 在他的回答中所描述的那样,您不太正确,因为您没有减少尝试的字节数发送第二次和后续呼叫。
What is the best practice to read from a file and send it back?
同上