如果将大文件加载到C Web服务器的内存缓冲区中,会发生什么情况

如果将大文件加载到C Web服务器的内存缓冲区中,会发生什么情况,c,memory,tcp,webserver,C,Memory,Tcp,Webserver,我正在用C语言制作一个简单的web服务器,用于教育目的中的静态文件。我制作了一个函数,将文件发送到客户端,并为整个文件分配内存块。如果服务器硬件有4GB内存,而客户机请求的内存很大,例如,数据库文件大小为5GB,该怎么办。它不会使我的应用程序崩溃吗 my serve_file函数的主体(请注意,省略了错误处理): 最好的方法是使用循环在可管理的块中读取和提供数据。这样,文件有多大都无关紧要。您的方法可能会也可能不会导致系统崩溃。如果它没有崩溃,很可能会开始使用虚拟内存将数据分页到磁盘。这将导致大

我正在用C语言制作一个简单的web服务器,用于教育目的中的静态文件。我制作了一个函数,将文件发送到客户端,并为整个文件分配内存块。如果服务器硬件有4GB内存,而客户机请求的内存很大,例如,数据库文件大小为5GB,该怎么办。它不会使我的应用程序崩溃吗

my serve_file函数的主体(请注意,省略了错误处理):


最好的方法是使用循环在可管理的块中读取和提供数据。这样,文件有多大都无关紧要。您的方法可能会也可能不会导致系统崩溃。如果它没有崩溃,很可能会开始使用虚拟内存将数据分页到磁盘。这将导致大量的颠簸并降低系统速度,如果其他程序正在尝试运行,这一点尤其糟糕

如果服务器硬件有4GB内存,而客户机请求的内存很大,例如,数据库文件大小为5GB,该怎么办。它不会使我的应用程序崩溃吗

也许吧。也许不是。C标准中没有任何内容直接说明这个问题。即使在实践中,C实现支持的分配对象的大小也不一定局限于物理内存的大小。现代机器有虚拟内存系统,可以想象,通过虚拟内存系统可以支持您描述的分配。如果分配确实成功,那么就没有特别的理由认为服务器会崩溃

这里的主要风险是您没有检查分配是否成功。在看似合理的失败事件中,
malloc()
调用将返回一个空指针。将空指针作为
fread()
的第一个参数传递将产生未定义的行为。在这种情况下,这很可能表现为崩溃,但不需要这样做。如果您检查
malloc()
调用的返回值,那么您可以正常地失败,而不是崩溃

我注意到您也没有检查
fread()
的返回值。如果失败,那么您可能会向客户端发送垃圾。作为一般规则,如果确实关心是否发生了任何错误,则应该检查函数调用的返回值以查找错误指示器


话虽如此,确实有更好的方法来做你想做的事情。除了存在严重的失败风险外,在发送之前将整个文件读入内存可能会在传输到客户机实际开始之前引入明显的延迟。很可能足以自动或自动超时。从这个意义上讲,以较小的篇幅阅读很可能会快得多。还有其他选择,例如将文件映射到内存中,而不是实际读取它。

如果您以一种半体面的方式编写它,则不会。分配一大块内存并一次性读取整个文件显然不是最好的方法。你能想出其他的选择吗?是的,我想过一块一块地发送文件,但是它对大文件来说足够快吗?此外,在实现过程中也存在一些问题,但这不是我认为定义“足够快”的另一个问题。谷歌的速度够快吗?可能不会。快到足以完成任务或家庭项目。可能无论如何,限制因素可能是网络,使用合理的块大小不会对网络产生太大影响。对于性能的调整不应该提前完成。这应该利用零拷贝,这比将文件数据拷贝到用户空间然后再拷贝回内核空间要快。我以前从未实际使用过这个,但我认为应该在这里使用。谢谢。正如我在我的问题下的评论中所说,分块发送是否足够快?只要它们不是太小,就不应该成为问题。我已经做过很多次了。确切的“最佳”大小可能很难确定,但我会使用从1Kb到1MB的任何大小。如果你有很多内存,你可以更高,但这可能并不重要,因为网络带宽可能是限制因素,而不是内存。我提到我在这里省略了错误处理以减少代码大小。当然,应该检查所有返回值。谢谢你的回复
long fsize;
FILE *fp = fopen(filename, "rb");
fseek(fp, 0, SEEK_END);
fsize = ftell(fp);
rewind(fp);

char *buf = (char*) malloc(fsize);

fread(buf, fsize, 1, fp);

Server_TCP_Send(socket, buf, fsize);
fclose(fp);
free(buf);