如何使用 C 从头构建一个简单的 HTTP 服务器
您可能想知道 Web 服务器如何“提供”文件,以及它们如何将文件拼凑成一个显示在您屏幕上的网站。了解 Web 服务器的实现方式无疑是“边构建边学习”的好方法。
虽然用 C 语言实现 Web 服务器听起来非常基础和复杂,但它或许能帮助你更好地理解 HTTP 的工作原理,以及服务器与客户端的实际交互方式。让我们开始吧!
Socket 的工作原理
在构建 Web 服务器之前,您需要了解“套接字”的工作原理。
如果将主机上运行的程序(或进程)比作一栋房子,那么套接字就像一扇门,用来接收和发送邮件。当屋子里的人收发信件时,他/她可以完全不知道邮件在外面是如何传递的。
使用套接字网络接口,我们的 Web 服务器可以使用 C 标准库包中的一组函数<sys/socket.h>
,并通过互联网与客户端“通信”。这些客户端也使用套接字与我们通信,因此套接字基本上就像是一个关于如何在互联网上相互通信的共识。
设置服务器套接字
首先,我创建并配置了服务器的套接字。我配置了以下几项:
- AF_INET:使用 IPv4(相对于 IPv6)
- SOCK_STREAM:使用 TCP(相对于 UDP)
- INADDR_ANY:服务器接受来自任何网络接口的连接
bind()
将套接字绑定到端口(我在这里使用 8080)意味着套接字将监听任何尝试连接到端口 8080 的客户端。listen()
获取待处理连接的最大数量(我将其设置为 10)。
现在,我的服务器已全部设置完毕并准备好接受传入的客户端连接。
处理客户端连接
服务器启动并运行后,下一步就是处理传入的客户端连接。我使用了一个无限循环来持续监听新客户端。
当客户端连接时,服务器会接受该连接并创建一个新线程来处理客户端的 HTTP 请求。这样,服务器就可以同时处理多个客户端。
我定义了一个函数handle_client()
来处理来自客户端的传入请求。这里我只实现了 GET 函数,因为它很好地展示了服务器如何向客户端“提供”文件。
handle_client()
接收请求数据,提取请求的文件名,并解码 URL(例如,将 %20 转换为空格)。然后,识别文件扩展名,构建包含请求文件的 HTTP 响应,并将其发送回客户端。
构建 HTTP 响应
在里面handle_client()
,我定义了另一个build_http_response()
构造 HTTP 响应的函数,其中包含标头和实际文件。
该函数首先根据文件扩展名构建一个具有相应 MIME 类型的 HTTP 标头(例如,如果请求的是 .jpg,则 MIME 类型为 image/jpeg)。如果文件不存在,则该函数会创建一个 404 Not Found 响应。否则,它会获取文件的大小,并将 200 OK 标头附加到响应缓冲区。
接下来,它读取文件内容并将其附加到响应缓冲区。返回的响应缓冲区handle_client()
将发送回客户端。我将 BUFFER_SIZE 设置为 1MB,这意味着服务器可以处理最大 1MB 的任何 HTTP 响应。
一个正在运行的 HTTP 服务器!
总而言之,我希望本教程可以帮助您更好地理解服务器实际上如何与客户端交互。
这是完整代码的github repo 。
🌟 特别赠品
CodeCrafters 有一个编程挑战,可以指导你使用任何语言逐步构建 HTTP 服务器。使用我的推荐链接加入即可享受 40% 折扣🚀
文章来源:https://dev.to/jeffreythecoder/how-i-built-a-simple-http-server-from-scratch-using-c-739