在本文中,我们展示了如何使用HttpListener类在C#中创建简单的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("http://localhost: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("http://localhost: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("http://localhost: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("http://localhost: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 = "http://localhost: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("http://localhost: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#教程。