C# HttpListener
最后修改于 2023 年 7 月 5 日
在本文中,我们将展示如何使用 C# 中的 HttpListener 类创建简单的 HTTP 服务器。
超文本传输协议 (HTTP) 是一种用于分布式、协作式、超媒体信息系统的应用协议。 HTTP 是万维网数据通信的基础。
HttpListener 是一个简单的、以编程方式控制的 HTTP 协议监听器。 它可用于创建 HTTP 服务器。 它位于 System.Net 命名空间中。
HTTP 服务器使用 HTTP(超文本传输协议)来响应浏览器、爬虫程序或 curl 或 wget 等工具发出的客户端请求。它使用 Web 资源(例如 HTML 页面、图像或多媒体)或 HTTP 错误消息进行响应。
C# HttpListener 状态
在第一个例子中,服务器响应一个状态码。 HTTP 响应状态代码指示特定的 HTTP 请求是否已成功完成。
using System.Net;
using var listener = new HttpListener();
listener.Prefixes.Add("https://:8001/");
listener.Start();
Console.WriteLine("Listening on port 8001...");
while (true)
{
HttpListenerContext ctx = listener.GetContext();
using HttpListenerResponse resp = ctx.Response;
resp.StatusCode = (int) HttpStatusCode.OK;
resp.StatusDescription = "Status OK";
}
在该示例中,监听器响应 HttpStatusCode.OK。
using var listener = new HttpListener();
listener.Prefixes.Add("https://:8001/");
我们创建一个 HttpListener 实例,并添加监听器监听的 URL 和端口。
listener.Start();
使用 Start,我们开始接收请求。
while (true)
{
HttpListenerContext ctx = listener.GetContext();
using HttpListenerResponse resp = ctx.Response;
在循环内部,调用 GetContext,它等待传入的请求并在收到请求时返回。 从上下文中,我们获得响应对象。 这是发送回客户端的对象。
resp.StatusCode = (int) HttpStatusCode.OK; resp.StatusDescription = "Status OK";
我们将统计代码和描述写入响应对象。
$ curl localhost:8001 -i HTTP/1.1 200 Status OK Server: Microsoft-NetCore/2.0 Date: Mon, 04 Jul 2022 12:38:24 GMT Transfer-Encoding: chunked
C# HttpListener 发送文本
下一个示例将文本数据发送到客户端。
using System.Net;
using System.Text;
using var listener = new HttpListener();
listener.Prefixes.Add("https://:8001/");
listener.Start();
Console.WriteLine("Listening on port 8001...");
while (true)
{
HttpListenerContext context = listener.GetContext();
HttpListenerRequest req = context.Request;
Console.WriteLine($"Received request for {req.Url}");
using HttpListenerResponse resp = context.Response;
resp.Headers.Set("Content-Type", "text/plain");
string data = "Hello there!";
byte[] buffer = Encoding.UTF8.GetBytes(data);
resp.ContentLength64 = buffer.Length;
using Stream ros = resp.OutputStream;
ros.Write(buffer, 0, buffer.Length);
}
服务器发送一条文本消息。
HttpListenerRequest req = context.Request;
Console.WriteLine($"Received request for {req.Url}");
在服务器端,我们还记录请求的 URL。
using HttpListenerResponse resp = context.Response;
resp.Headers.Set("Content-Type", "text/plain");
在响应标头中,我们将 Content-Type 设置为 text/plain,以提示客户端期望哪种数据。
string data = "Hello there!"; byte[] buffer = Encoding.UTF8.GetBytes(data);
我们将消息转换为字节。
resp.ContentLength64 = buffer.Length;
我们设置内容长度。
using Stream ros = resp.OutputStream; ros.Write(buffer, 0, buffer.Length);
最后,我们将字节写入输出流。
$ curl localhost:8001 Hello there!
C# HttpListener 用户代理
User-Agent 请求标头是一个字符串,允许服务器和网络对等方识别请求用户代理的应用程序、操作系统、供应商和/或版本。
using System.Net;
using System.Text;
using var listener = new HttpListener();
listener.Prefixes.Add("https://:8001/");
listener.Start();
Console.WriteLine("Listening on port 8001...");
while (true)
{
HttpListenerContext ctx = listener.GetContext();
HttpListenerRequest req = ctx.Request;
string? ua = req.Headers.Get("User-Agent");
using HttpListenerResponse resp = ctx.Response;
resp.Headers.Set("Content-Type", "text/plain");
string data = ua ?? "unknown";
byte[] buffer = Encoding.UTF8.GetBytes(data);
resp.ContentLength64 = buffer.Length;
using Stream ros = resp.OutputStream;
ros.Write(buffer, 0, buffer.Length);
}
监听器从客户端请求检索 User-Agent 标头并将其发回。
string? ua = req.Headers.Get("User-Agent");
从请求标头中,我们获取 User-Agent 字段。
string data = ua ?? "unknown"; byte[] buffer = Encoding.UTF8.GetBytes(data); resp.ContentLength64 = buffer.Length; using Stream ros = resp.OutputStream; ros.Write(buffer, 0, buffer.Length);
我们将文本值转换为字节,并将字节写入响应输出流。
var url = "https://:8001";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("User-Agent", "C# program");
var res = await client.GetStringAsync(url);
Console.WriteLine(res);
我们创建一个 HttpClient,它向服务器发送请求;它还设置 User-Agent 标头字段。
$ dotnet run C# program
C# HttpListener 发送图像
在下一个例子中,服务器发送一个图像。
using System.Net;
using System.Text;
using var listener = new HttpListener();
listener.Prefixes.Add("https://:8001/");
listener.Start();
Console.WriteLine("Listening on port 8001...");
while (true)
{
HttpListenerContext ctx = listener.GetContext();
HttpListenerRequest req = ctx.Request;
string? path = ctx.Request.Url?.LocalPath;
if (path == "/image")
{
sendImage(ctx);
}
else
{
notFound(ctx);
}
}
void notFound(HttpListenerContext ctx)
{
using HttpListenerResponse resp = ctx.Response;
resp.Headers.Set("Content-Type", "text/plain");
using Stream ros = resp.OutputStream;
ctx.Response.StatusCode = (int)HttpStatusCode.NotFound;
string err = "404 - not found";
byte[] ebuf = Encoding.UTF8.GetBytes(err);
resp.ContentLength64 = ebuf.Length;
ros.Write(ebuf, 0, ebuf.Length);
}
void sendImage(HttpListenerContext ctx)
{
using HttpListenerResponse resp = ctx.Response;
resp.Headers.Set("Content-Type", "image/png");
byte[] buf = File.ReadAllBytes("public/img/sid.png");
resp.ContentLength64 = buf.Length;
using Stream ros = resp.OutputStream;
ros.Write(buf, 0, buf.Length);
}
在 public/img 目录中,我们有一个 PNG 文件。
string? path = ctx.Request.Url?.LocalPath;
从请求中,我们获取本地路径值。
if (path == "/image")
{
sendImage(ctx);
}
else
{
notFound(ctx);
}
如果路径等于 /image,我们将使用 sendImage 发送图像。 否则,我们发送未找到错误。
void notFound(HttpListenerContext ctx)
{
using HttpListenerResponse resp = ctx.Response;
resp.Headers.Set("Content-Type", "text/plain");
using Stream ros = resp.OutputStream;
ctx.Response.StatusCode = (int)HttpStatusCode.NotFound;
string err = "404 - not found";
byte[] ebuf = Encoding.UTF8.GetBytes(err);
resp.ContentLength64 = ebuf.Length;
ros.Write(ebuf, 0, ebuf.Length);
}
notFound 方法将 404 错误消息发送回客户端。 这是一个标准的 HTTP 错误消息,指示未找到该资源。
void sendImage(HttpListenerContext ctx)
{
using HttpListenerResponse resp = ctx.Response;
resp.Headers.Set("Content-Type", "image/png");
byte[] buf = File.ReadAllBytes("public/img/sid.png");
resp.ContentLength64 = buf.Length;
using Stream ros = resp.OutputStream;
ros.Write(buf, 0, buf.Length);
}
在 sendImage 内部,我们使用 File.ReadAllBytes 读取图像,并使用 Write 将字节数组写入输出流。 我们还设置适当的 image/png 内容类型。
来源
在本文中,我们使用 HttpListener 创建了简单的 HTTP 服务器。
作者
列出所有 C# 教程。