从20行代码理解HTTP服务器:用原始Socket揭开Web协议的神秘面纱
本文通过一个仅20行的C#代码示例,深入讲解HTTP服务器如何工作,帮助你理解浏览器和服务器之间的通信本质。引言:HTTP的真相
当我们每天使用浏览器访问网站时,是否曾思考过背后发生了什么?浏览器和服务器之间到底在交流什么?今天,我将用最精简的代码(仅20行!)展示HTTP服务器的核心原理,并逐步扩展为一个功能完整的服务器。
核心代码:20行的HTTP服务器
using System.Net;
using System.Net.Sockets;
using System.Text;
class CoreHttpServer
{
static void Main()
{
// 1. 创建TCP监听器
TcpListener server = new TcpListener(IPAddress.Any, 9011);
server.Start();
Console.WriteLine("服务器启动...");
while (true)
{
// 2. 接受连接
TcpClient client = server.AcceptTcpClient();
// 3. 读取请求
NetworkStream stream = client.GetStream();
byte[] buffer = new byte;
int bytes = stream.Read(buffer, 0, buffer.Length);
// 4. 构建响应
string html = "<h1>Hello Socket!</h1><p>原始HTTP</p>";
string response =
"HTTP/1.1 200 OK\r\n" +
"Content-Type: text/html\r\n" +
$"Content-Length: {Encoding.UTF8.GetByteCount(html)}\r\n" +
"\r\n" + html;
// 5. 发送响应
byte[] data = Encoding.UTF8.GetBytes(response);
stream.Write(data, 0, data.Length);
client.Close();
}
}
}这20行代码包含了HTTP服务器的一切本质!让我们逐行解析:
第一行:建立TCP连接通道
TcpListener server = new TcpListener(IPAddress.Any, 9011);这行代码创建了一个TCP监听器,就像是开了一家商店,门牌号是9011:
[*]IPAddress.Any:监听所有网络接口
[*]9011:端口号,服务器的"门牌号"
关键理解:HTTP建立在TCP之上。TCP是"可靠传输管道",HTTP是"管道中传输的文本协议"。
第二行:等待客户上门
TcpClient client = server.AcceptTcpClient();当浏览器访问 http://localhost:9011 时:
[*]浏览器建立TCP连接到端口9011
[*]AcceptTcpClient() 接受这个连接
[*]返回一个 TcpClient 对象,代表这个连接通道
第三行:接收浏览器的"订单"
NetworkStream stream = client.GetStream();
byte[] buffer = new byte;
int bytes = stream.Read(buffer, 0, buffer.Length);这里发生了以下事情:
浏览器发送的原始文本:
GET / HTTP/1.1\r\n
Host: localhost:9011\r\n
User-Agent: Mozilla/5.0\r\n
Accept: text/html\r\n
\r\n注意最后的 \r\n\r\n(空行),这是HTTP协议规定的:头部结束的标记。
第四行:准备"商品"(构建响应)
string html = "<h1>Hello Socket!</h1><p>原始HTTP</p>";
string response =
"HTTP/1.1 200 OK\r\n" +
"Content-Type: text/html\r\n" +
$"Content-Length: {Encoding.UTF8.GetByteCount(html)}\r\n" +
"\r\n" + html;HTTP响应由三部分组成:
1. 状态行:HTTP/1.1 200 OK
[*]HTTP/1.1:协议版本
[*]200:状态码(成功)
[*]OK:状态描述
2. 响应头部
[*]Content-Type: text/html:告诉浏览器这是HTML
[*]Content-Length: ...:告诉浏览器内容有多长(至关重要!)
3. 空行分隔
[*]\r\n:必须的空行,分隔头部和正文
4. 响应正文
[*]HTML内容
第五行:发送"商品"给客户
byte[] data = Encoding.UTF8.GetBytes(response);
stream.Write(data, 0, data.Length);
client.Close();文本 → 字节 → 通过网络发送 → 关闭连接。完整的一次HTTP交互完成!
从20行到完整服务器
现在,让我们基于这20行核心代码,构建一个功能更完整的服务器:
1. 添加请求解析
// 解析浏览器请求的路径
string requestText = Encoding.UTF8.GetString(buffer, 0, bytes);
string[] lines = requestText.Split("\r\n");
string requestLine = lines;
string[] parts = requestLine.Split(' ');
string path = parts.Length > 1 ? parts : "/";这样我们就可以知道用户请求的是 /、/about 还是其他路径。
2. 根据路径返回不同内容
string html;
if (path == "/")
{
html = "<h1>主页</h1>";
}
else if (path == "/about")
{
html = "<h1>关于页面</h1>";
}
else
{
html = "<h1>404 - 页面未找到</h1>";
}3. 添加文件读取功能
这是从内存响应到文件系统的关键跨越:
static string ReadHtmlFile(string fileName){ try { // 检查文件是否存在 if (!File.Exists(fileName)) { throw new FileNotFoundException(); } // 读取文件内容 string content = File.ReadAllText(fileName, Encoding.UTF8); Console.WriteLine($"
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! 感谢分享,下载保存了,貌似很强大 懂技术并乐意极积无私分享的人越来越少。珍惜
页:
[1]