当前位置: 首页 > news >正文

使用C#的Socket从头实现的带有文件上传和下载功能的HTTP服务器

使用C#和Socket从头实现的带有文件上传和下载功能的HTTP服务器。它支持GET、POST请求方法,并能处理URL参数、请求体以及文件上传和下载。

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;class HttpServer
{public static void Main(string[] args){const int port = 8080;TcpListener listener = new TcpListener(IPAddress.Any, port);listener.Start();Console.WriteLine("HTTP server is running on port {0}...", port);while (true){TcpClient client = listener.AcceptTcpClient();ProcessClientRequest(client);}}public static void ProcessClientRequest(TcpClient client){using (NetworkStream stream = client.GetStream()){// 读取请求数据byte[] buffer = new byte[4096];int bytesRead = stream.Read(buffer, 0, buffer.Length);string requestString = Encoding.UTF8.GetString(buffer, 0, bytesRead);// 解析请求HttpRequest request = ParseRequest(requestString);// 构造响应数据HttpResponse response = BuildResponse(request);// 发送响应头byte[] responseHeaderBytes = Encoding.UTF8.GetBytes(response.GetHeaderString());stream.Write(responseHeaderBytes, 0, responseHeaderBytes.Length);// 发送响应体(如果有)if (response.ContentStream != null){byte[] bufferBytes = new byte[4096];int bytesToRead;while ((bytesToRead = response.ContentStream.Read(bufferBytes, 0, bufferBytes.Length)) > 0){stream.Write(bufferBytes, 0, bytesToRead);}response.ContentStream.Close();}}client.Close();}public static HttpRequest ParseRequest(string requestString){var request = new HttpRequest();string[] lines = requestString.Split(new[] { "\r\n" }, StringSplitOptions.None);// 解析请求行string[] requestLineParts = lines[0].Split(' ');request.Method = requestLineParts[0].ToUpper();request.Path = requestLineParts[1];// 解析请求头for (int i = 1; i < lines.Length; i++){string[] headerParts = lines[i].Split(':');if (headerParts.Length == 2){string key = headerParts[0].Trim();string value = headerParts[1].Trim();request.Headers[key] = value;}}// 解析请求体(仅对POST请求处理)if (request.Method == "POST"){int bodyIndex = Array.IndexOf(lines, "");if (bodyIndex != -1 && bodyIndex < lines.Length - 1){request.Body = lines[bodyIndex + 1];}}return request;}public static HttpResponse BuildResponse(HttpRequest request){var response = new HttpResponse();// 设置响应头信息response.StatusCode = 200;response.StatusDescription = "OK";response.Headers["Content-Type"] = "text/plain; charset=utf-8";// 处理文件上传if (request.Method == "POST" && request.Headers.ContainsKey("Content-Disposition")){string filename = GetFilenameFromContentDisposition(request.Headers["Content-Disposition"]);using (FileStream fileStream = File.Create(filename)){using (StreamWriter writer = new StreamWriter(fileStream)){writer.Write(request.Body);}}response.SetContent("File uploaded successfully.");}// 处理文件下载else if (request.Method == "GET" && request.Path.StartsWith("/download/")){string filepath = request.Path.Substring("/download/".Length);if (File.Exists(filepath)){response.StatusCode = 200;response.StatusDescription = "OK";response.Headers["Content-Type"] = "application/octet-stream";response.Headers["Content-Disposition"] = $"attachment; filename=\"{Path.GetFileName(filepath)}\"";response.ContentStream = File.OpenRead(filepath);}else{response.StatusCode = 404;response.StatusDescription = "Not Found";response.SetContent("File not found.");}}// 默认返回文本内容else{string content = "Welcome to the HTTP server.";response.SetContent(content);}return response;}public static string GetFilenameFromContentDisposition(string contentDisposition){const string keyword = "filename=\"";int startIndex = contentDisposition.IndexOf(keyword) + keyword.Length;int endIndex = contentDisposition.IndexOf("\"", startIndex);return contentDisposition.Substring(startIndex, endIndex - startIndex);}
}class HttpRequest
{public string Method { get; set; }public string Path { get; set; }public IDictionary<string, string> Headers { get; set; } = new Dictionary<string, string>();public string Body { get; set; }
}class HttpResponse
{public int StatusCode { get; set; }public string StatusDescription { get; set; }public IDictionary<string, string> Headers { get; set; } = new Dictionary<string, string>();public Stream ContentStream { get; set; }public void SetContent(string content){byte[] contentBytes = Encoding.UTF8.GetBytes(content);ContentStream = new MemoryStream(contentBytes);Headers["Content-Length"] = contentBytes.Length.ToString();}public string GetHeaderString(){StringBuilder builder = new StringBuilder();builder.AppendFormat("HTTP/1.1 {0} {1}\r\n", StatusCode, StatusDescription);foreach (var header in Headers){builder.AppendFormat("{0}: {1}\r\n", header.Key, header.Value);}builder.Append("\r\n");return builder.ToString();}
}

http://www.lryc.cn/news/197048.html

相关文章:

  • 【OSPF Loading、FULL状态与display ospf peer brief命令、OSPF的数据库讲解】
  • 除氟树脂在工业、市政含氟废水处理中的应用
  • 模拟地和数字地的区别
  • Druid连接池最小连接数设置失效问题
  • Javascript数据类型和类型转换
  • 冲刺十五届蓝桥杯P0005单词分析
  • php获取10年内的年份并加入下拉列表
  • 2020年亚太杯APMCM数学建模大赛B题美国总统的经济影响分析求解全过程文档及程序
  • 保护隐私就是在保护自己!如何在Android上更改应用程序权限
  • Linux/Ubuntu 安装 Java运行环境
  • vue2 中activated和deactivated是详细解说
  • C# GFPGAN 图像(人脸面部)修复
  • ruoyi项目登录验证变更
  • maven依赖冲突以及解决方法
  • K8S常用的一些命令及工具
  • Atlas 200I DK目标检测与追踪技术记录
  • php如何在header增加key,sign,timestamp?怎么鉴权?
  • 从代码入手理解卡尔曼滤波器的原理之使用Eigen实现二维卡尔曼滤波器(七)
  • 文件的操作
  • left join时筛选条件对查询结果的
  • CVE-2020-9483 apache skywalking SQL注入漏洞
  • PaddleX解决分类、检测两大场景问题?实战精讲教程来了!
  • Hive用户中文使用手册系列(二)
  • 2023年中国清净剂行业需求现状及前景分析[图]
  • 文心一言 VS 讯飞星火 VS chatgpt (115)-- 算法导论10.2 8题
  • Redis的BitMap实现分布式布隆过滤器
  • 【linux API分析】module_init
  • NSDT孪生编辑器助力智慧城市
  • 如何优雅的实现接口统一调用
  • tomcat、nginx实现四层转发+七层代理+动静分离实验