当前位置: 首页 > 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();}
}

相关文章:

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

使用C#和Socket从头实现的带有文件上传和下载功能的HTTP服务器。它支持GET、POST请求方法&#xff0c;并能处理URL参数、请求体以及文件上传和下载。 using System; using System.IO; using System.Net; using System.Net.Sockets; using System.Text;class HttpServer {publi…...

【OSPF Loading、FULL状态与display ospf peer brief命令、OSPF的数据库讲解】

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大二在校生&#xff0c;喜欢编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️ 零基…...

除氟树脂在工业、市政含氟废水处理中的应用

含氟废水的不达标排放对自然环境有很大的危害&#xff0c;氟化物离子可以累积在土壤和水体中&#xff0c;从而对生态系统造成破坏。大量的氟化物离子会对植物生长产生不良影响&#xff0c;并对水生生物造成毒性作用&#xff0c;严重时还可能导致生态灾难。氟化物离子如果没有得…...

模拟地和数字地的区别

模拟地和数字地的主要区别体现在设计目的、处理技术、数据类型和数据精度四个方面。 设计目的&#xff1a;模拟地的主要设计目的是分析时空数据、进行模型和预测&#xff0c;它主要关注动态变化和过程。而数字地的主要设计目的是数据的存储、管理、查询和分析&#xff0c;在地…...

Druid连接池最小连接数设置失效问题

问题发现&#xff1a; 配置 当项目启动后 线程池确实是初始化了5条连接&#xff0c;但是当项目运行一段时间后&#xff0c;5条连接确消失了&#xff0c;只会程序用到得时候&#xff0c;再去初始化连接&#xff0c;这样有点违背了参数设置得意义&#xff0c;后来通过查阅资料发…...

Javascript数据类型和类型转换

Javascript数据类型和类型转换 在JavaScript中&#xff0c;理解数据类型&#xff0c;如何区分它们&#xff0c;以及它们如何被转换是至关重要的。在这篇文章中&#xff0c;我们将探讨这些主题&#xff0c;以帮助巩固你的JavaScript基础。 基础数据类型和引用数据类型 当涉及…...

冲刺十五届蓝桥杯P0005单词分析

文章目录 题目分析代码 题目 单词分析 分析 统计字符串中字母出现的次数&#xff0c;可以采用哈希表&#xff0c;代码采用的是数组来存储字符&#xff0c;将字符-97&#xff0c;得到对应的数组下标&#xff0c;将对应下标的数组&#xff1b;找到数组元素最大的下标&#xff…...

php获取10年内的年份并加入下拉列表

要实现的效果 在html中内嵌php循环将数组中的年份加入下拉列表 <div class="form-group"><label>年份:</label><div class="input-group"><div class="input-group-prepend"><span class="input-group-te…...

2020年亚太杯APMCM数学建模大赛B题美国总统的经济影响分析求解全过程文档及程序

2020年亚太杯APMCM数学建模大赛 B题 美国总统的经济影响分析 原题再现&#xff1a; 美国总统选举每四年举行一次。 2020年是美国总统大选年&#xff0c;共和党候选人唐纳德特朗普和民主党对手乔拜登竞选总统。 甲乙双方候选人在金融贸易&#xff0c;经济金融治理&#xff0c;…...

保护隐私就是在保护自己!如何在Android上更改应用程序权限

如果你关心隐私&#xff0c;知道如何在Android上更改应用程序权限将成为一项非常重要的技能。即使是最好的安卓应用程序也可以对手机的功能和数据进行广泛的访问&#xff0c;因此准确控制它们的使用范围会有所帮助。 一旦你在手机上加载了应用程序&#xff0c;你可能会注意到它…...

Linux/Ubuntu 安装 Java运行环境

linux下安装Java运行环境 1、下载安装包 .tar.gz 先在官网下载 JDK 点击这里 在这里要选择对应的 JDK 版本&#xff0c;一般我们目前选择JDK8 点击这里 2、在 /usr/local/ 目录下创建Java文件夹 cd /usr/local/ mkdir java3、将下载的文件通过FTP程序上传到刚刚创建的Java文…...

vue2 中activated和deactivated是详细解说

activated 和 deactivated 是 Vue.js 中的生命周期钩子函数&#xff0c;主要用于处理组件在 keep-alive 缓存中进入和离开时的行为。 这些钩子函数通常用于在组件进入缓存时执行特定的操作&#xff0c;以及在组件离开缓存时执行清理操作。 下面是关于这两个钩子函数的用例和示例…...

C# GFPGAN 图像(人脸面部)修复

效果 项目 代码 using Microsoft.ML.OnnxRuntime; using Microsoft.ML.OnnxRuntime.Tensors; using OpenCvSharp; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.Windows.Forms;namespace 图像修复 {pu…...

ruoyi项目登录验证变更

背景&#xff1a;我用的是ruoyi-vue3.8.6版本&#xff0c;因公司需要使用window的域用户进行登录验证&#xff0c;因此原有的ruoyi登录验证方法就得替换掉 1. 首先登录系统添加一些域账号&#xff0c;以确保登录方式更改后&#xff0c;能在sys_user中找到该账号&#xff0c;因…...

maven依赖冲突以及解决方法

什么是依赖冲突 依赖冲突是指项目依赖的某一个jar包&#xff0c;有多个不同的版本&#xff0c;因而造成类包版本冲突 依赖冲突的原因 依赖冲突很经常是类包之间的间接依赖引起的。每个显式声明的类包都会依赖于一些其它的隐式类包&#xff0c;这些隐式的类包会被maven间接引…...

K8S常用的一些命令及工具

已json格式输出 [rootk8master1 ~]# yum install epel-release [rootk8master1 ~]# yum -y install jq [rootk8master1 ~]# kubectl get --raw /api/v1/namespaces/dev | jq {"kind": "Namespace","apiVersion": "v1","metadata…...

Atlas 200I DK目标检测与追踪技术记录

数据集 数据集采用MOT系列&#xff0c;MOT是多目标追踪常用数据集&#xff0c;MOT数据集对数据集进行了分帧&#xff0c;如要获得视频&#xff0c;需要先利用opencv里的cv2.VideoWriter模块便利图片文件夹&#xff0c;具体代码如下&#xff1a; import os import cv2img_path…...

php如何在header增加key,sign,timestamp?怎么鉴权?

在PHP中&#xff0c;您可以通过在HTTP请求的Header中增加Key、Sign和Timestamp等信息来进行安全性鉴权。 以下是一种基本的思路和示例&#xff0c;用于说明如何实现这种鉴权机制&#xff1a; 生成Key和Sign&#xff1a; 服务端和客户端之间共享一个密钥&#xff08;Key&#x…...

从代码入手理解卡尔曼滤波器的原理之使用Eigen实现二维卡尔曼滤波器(七)

当然可以。现在,给定了矩阵和向量的具体定义,我们可以更详细地解释这些变量的意义,并确定卡尔曼滤波器的维度。 F (状态转移矩阵): F 是一个2x2的矩阵,给定为:1 0 0 1这意味着系统的状态从时刻t到t+1没有实质变化,即每个状态都保持不变。 H (观测矩阵): H 也是一个2x2的矩…...

文件的操作

前言&#xff1a;哈喽小伙伴们好久不见&#xff0c;国庆假期已经结束&#xff0c;接下来我们还是要马不停蹄的投入到学习当中&#xff0c;只有尽快调整状态回归学习&#xff0c;才能弯道超车。 今天我们一起来学习C语言——文件操作。 本篇文章讲到的所有函数均需要头文件#inc…...

uniapp 对接腾讯云IM群组成员管理(增删改查)

UniApp 实战&#xff1a;腾讯云IM群组成员管理&#xff08;增删改查&#xff09; 一、前言 在社交类App开发中&#xff0c;群组成员管理是核心功能之一。本文将基于UniApp框架&#xff0c;结合腾讯云IM SDK&#xff0c;详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

深度学习水论文:mamba+图像增强

&#x1f9c0;当前视觉领域对高效长序列建模需求激增&#xff0c;对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模&#xff0c;以及动态计算优势&#xff0c;在图像质量提升和细节恢复方面有难以替代的作用。 &#x1f9c0;因此短时间内&#xff0c;就有不…...

LLMs 系列实操科普(1)

写在前面&#xff1a; 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容&#xff0c;原视频时长 ~130 分钟&#xff0c;以实操演示主流的一些 LLMs 的使用&#xff0c;由于涉及到实操&#xff0c;实际上并不适合以文字整理&#xff0c;但还是决定尽量整理一份笔…...