C#实现WEB服务器

2023-05-16

一、HTTP协议的作用原理

WWW是以Internet作为传输媒介的一个应用系统,WWW网上最基本的传输单位是Web网页。WWW的工作基于客户机/服务器计算模型,由Web 浏览器(客户机)和Web服务器(服务器)构成,两者之间采用超文本传送协议(HTTP)进行通信。HTTP协议是基于TCP/IP协议之上的协议,是Web浏览器和Web服务器之间的应用层协议,是通用的、无状态的、面向对象的协议。HTTP协议的作用原理包括四个步骤:

连接:Web浏览器与Web服务器建立连接,打开一个称为socket(套接字)的虚拟文件,此文件的建立标志着连接建立成功。

请求:Web浏览器通过socket向Web服务器提交请求。HTTP的请求一般是GET或POST命令(POST用于FORM参数的传递)。GET命令的格式为:

GET 路径/文件名 HTTP/1.0

文件名指出所访问的文件,HTTP/1.0指出Web浏览器使用的HTTP版本。

应答:Web浏览器提交请求后,通过HTTP协议传送给Web服务器。Web服务器接到后,进行事务处理,处理结果又通过HTTP传回给Web浏览器,从而在Web浏览器上显示出所请求的页面。

例:假设客户机与www.mycomputer.com:8080/mydir/index.html建立了连接,就会发送GET命令:GET /mydir/index.html HTTP/1.0。主机名为www.mycomputer.com的Web服务器从它的文档空间中搜索子目录mydir的文件index.html。如果找到该文件,Web服务器把该文件内容传送给相应的Web浏览器。

为了告知 Web浏览器传送内容的类型,Web服务器首先传送一些HTTP头信息,然后传送具体内容(即HTTP体信息),HTTP头信息和HTTP体信息之间用一个空行分开。

常用的HTTP头信息有:

① HTTP 1.0 200 OK

这是Web服务器应答的第一行,列出服务器正在运行的HTTP版本号和应答代码。代码“200 OK”表示请求完成。

② MIME_Version:1.0

它指示MIME类型的版本。

③ content_type:类型

这个头信息非常重要,它指示HTTP体信息的MIME类型。如:content_type:text/html指示传送的数据是HTML文档。

④ content_length:长度值

它指示HTTP体信息的长度(字节)。

关闭连接:当应答结束后,Web浏览器与Web服务器必须断开,以保证其它Web浏览器能够与Web服务器建立连接。

二、C#实现Web服务器功能的程序设计

根据上述HTTP协议的作用原理,实现GET请求的Web服务器程序的方法如下:

创建TcpListener类对象,监听某端口(任意输入闲置端口 如:8080 )。

等待、接受客户机连接到该端口,得到与客户机连接的socket;

从与socket关联的输入流中读取一行客户机提交的请求信息,请求信息的格式为:GET 路径/文件名 HTTP/1.0

从请求信息中获取请求类型。如果请求类型是GET,则从请求信息中获取所访问的HTML文件名。没有HTML文件名时,则以index.html作为文件名;

如果HTML文件存在,则打开HTML文件,把HTTP头信息和HTML文件内容通过socket传回给Web浏览器,然后关闭文件。否则发送错误信息给Web浏览器;

关闭与相应Web浏览器连接的socket字。


实现的代码如下:
//webserver.cs//


namespace cnnbsun.webserver
{
using System; 
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading ;


class MyWebServer 
{

private TcpListener myListener ;
private int port = 8080 ; // 选者任何闲置端口

//开始兼听端口
//同时启动一个兼听进程
public MyWebServer()
{
try
{
//开始兼听端口
myListener = new TcpListener(port) ;
myListener.Start();
Console.WriteLine("Web Server Running... Press ^C to Stop...");
//同时启动一个兼听进程 ''StartListen''
Thread th = new Thread(new ThreadStart(StartListen));
th.Start() ;

}
catch(Exception e)
{
Console.WriteLine("兼听端口时发生错误 :" +e.ToString());
}
}
public void SendHeader(string sHttpVersion, string sMIMEHeader, int iTotBytes, string sStatusCode, ref Socket mySocket)
{

String sBuffer = "";

if (sMIMEHeader.Length == 0 )
{
sMIMEHeader = "text/html"; // 默认 text/html
}

sBuffer = sBuffer + sHttpVersion + sStatusCode + "\r\n";
sBuffer = sBuffer + "Server: cx1193719-b\r\n";
sBuffer = sBuffer + "Content-Type: " + sMIMEHeader + "\r\n";
sBuffer = sBuffer + "Accept-Ranges: bytes\r\n";
sBuffer = sBuffer + "Content-Length: " + iTotBytes + "\r\n\r\n";

Byte[] bSendData = Encoding.ASCII.GetBytes(sBuffer); 

SendToBrowser( bSendData, ref mySocket);

Console.WriteLine("Total Bytes : " + iTotBytes.ToString());

}

public void SendToBrowser(String sData, ref Socket mySocket)
{
SendToBrowser (Encoding.ASCII.GetBytes(sData), ref mySocket);
}

public void SendToBrowser(Byte[] bSendData, ref Socket mySocket)
{
int numBytes = 0;

try
{
if (mySocket.Connected)
{
if (( numBytes = mySocket.Send(bSendData, bSendData.Length,0)) == -1)
Console.WriteLine("Socket Error cannot Send Packet");
else
{
Console.WriteLine("No. of bytes send {0}" , numBytes);
}
}
else
Console.WriteLine("连接失败....");
}
catch (Exception e)
{
Console.WriteLine("发生错误 : {0} ", e );

}
}
public static void Main() 
{
MyWebServer MWS = new MyWebServer();
}
public void StartListen()
{

int iStartPos = 0;
String sRequest;
String sDirName;
String sRequestedFile;
String sErrorMessage;
String sLocalDir;
/注意设定你自己的虚拟目录/
String sMyWebServerRoot = "E:\\MyWebServerRoot\\"; //设置你的虚拟目录
//
String sPhysicalFilePath = "";
String sFormattedMessage = "";
String sResponse = "";


while(true)
{
//接受新连接
Socket mySocket = myListener.AcceptSocket() ;

Console.WriteLine ("Socket Type " +mySocket.SocketType ); 
if(mySocket.Connected)
{
Console.WriteLine("\nClient Connected!!\n==================\nCLient IP {0}\n",mySocket.RemoteEndPoint) ;

Byte[] bReceive = new Byte[1024] ;
int i = mySocket.Receive(bReceive,bReceive.Length,0) ;


//转换成字符串类型
string sBuffer = Encoding.ASCII.GetString(bReceive);


//只处理"get"请求类型
if (sBuffer.Substring(0,3) != "GET" )
{
Console.WriteLine("只处理get请求类型..");
mySocket.Close();
return;
}

// 查找 "HTTP" 的位置
iStartPos = sBuffer.IndexOf("HTTP",1);


string sHttpVersion = sBuffer.Substring(iStartPos,8);


// 得到请求类型和文件目录文件名
sRequest = sBuffer.Substring(0,iStartPos - 1);

sRequest.Replace("\\","/");


//如果结尾不是文件名也不是以"/"结尾则加"/"
if ((sRequest.IndexOf(".") <1) && (!sRequest.EndsWith("/")))
{
sRequest = sRequest + "/"; 
}


//得带请求文件名
iStartPos = sRequest.LastIndexOf("/") + 1;
sRequestedFile = sRequest.Substring(iStartPos);


//得到请求文件目录
sDirName = sRequest.Substring(sRequest.IndexOf("/"), sRequest.LastIndexOf("/")-3);


//获取虚拟目录物理路径
sLocalDir = sMyWebServerRoot;

Console.WriteLine("请求文件目录 : " + sLocalDir);

if (sLocalDir.Length == 0 )
{
sErrorMessage = "<H2>Error!! Requested Directory does not exists</H2><Br>";
SendHeader(sHttpVersion, "", sErrorMessage.Length, " 404 Not Found", ref mySocket);
SendToBrowser(sErrorMessage, ref mySocket);
mySocket.Close();
continue;
}


if (sRequestedFile.Length == 0 )
{
// 取得请求文件名
sRequestedFile = "index.html";
}


/
// 取得请求文件类型(设定为text/html)
/

String sMimeType = "text/html";

sPhysicalFilePath = sLocalDir + sRequestedFile;
Console.WriteLine("请求文件: " + sPhysicalFilePath);


if (File.Exists(sPhysicalFilePath) == false)
{

sErrorMessage = "<H2>404 Error! File Does Not Exists...</H2>";
SendHeader(sHttpVersion, "", sErrorMessage.Length, " 404 Not Found", ref mySocket);
SendToBrowser( sErrorMessage, ref mySocket);

Console.WriteLine(sFormattedMessage);
}

else
{
int iTotBytes=0;

sResponse ="";

FileStream fs = new FileStream(sPhysicalFilePath, FileMode.Open, FileAccess.Read, FileShare.Read);

BinaryReader reader = new BinaryReader(fs);
byte[] bytes = new byte[fs.Length];
int read;
while((read = reader.Read(bytes, 0, bytes.Length)) != 0) 
{
sResponse = sResponse + Encoding.ASCII.GetString(bytes,0,read);

iTotBytes = iTotBytes + read;

}
reader.Close(); 
fs.Close();

SendHeader(sHttpVersion, sMimeType, iTotBytes, " 200 OK", ref mySocket);
SendToBrowser(bytes, ref mySocket);
//mySocket.Send(bytes, bytes.Length,0);

}
mySocket.Close(); 
}
}
}


}

}

///结束

将文件编译成EXE文件,就实现了简单的WEB服务器功能!
可以设定一个虚拟目录,进行测试!
asp.net提供承载asp.net的方法。详细可以看这个例子: http://www.asp.net/Projects/Cassini/Download/Default.aspx?tabindex=0&tabid=1 ;


转载于:https://www.cnblogs.com/ymhtp/archive/2005/12/04/290518.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C#实现WEB服务器 的相关文章

  • Django - 缺少 1 个必需的位置参数:'request'

    我收到错误 get indiceComercioVarejista 缺少 1 个必需的位置参数 要求 当尝试访问 get indiceComercioVarejista 方法时 我不知道这是怎么回事 views from django ht
  • 为什么使用HTTP协议时需要指定端口号?

    即使我们使用HTTP协议 为什么还需要用IP地址指定端口号 例如 http xyz 8080 这到底是什么意思 我们已经知道 在使用 HTTP 时 请求将在端口 80 上提供服务 那么为什么我们要显式指定端口呢 HTTP 的默认端口为 80
  • Web Api - 不允许捕获 405 方法

    截至目前 Web api 应用程序针对 405 方法不允许错误返回以下响应正文 我正在尝试更改响应正文 但我不知道如何使用委托处理程序 ApiControllerActionSelector 或过滤器 谁能帮我捕获服务器端的 405 错误
  • MVC4更新部分视图

    我正在开发一个简单的 MVC 应用程序 我有主视图 部分视图和控制器 这是我的主要视图 model partitalViewTest Models Qset div class transbox style height 1 Html Pa
  • C# 构建一个 webservice 方法,它接受 POST 方法,如 HttpWebRequest 方法

    我需要一个接受 POST 方法的 Web 服务 访问我的服务器正在使用 POST 方法 它向我发送了一个 xml 我应该用一些 xml 进行响应 另一方面 当我访问他时 我已经使用 HttpWebRequest 类进行了管理 并且工作正常
  • 发送变量后的 wsdl 服务响应,php

    我是 SOAP WSDL 函数的新手 我有一位客户从一家从事汽车测试的公司获得了 wsdl 文件 我的客户是他们的分包商 他们告诉我们上传有关车牌 类别等信息 一旦详细信息发送完毕 服务器就会做出成功或失败的响应 请您协助 浏览不同的信息
  • 给定数十亿个 URL,如何确定重复内容 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我在一次编程面试中被问到这个问题 我在下面详细描述了这个问题 这是一个开放式问题 给定数十亿个 URL 深层链接 我如何对哪些 URL
  • VBA - 如何从网站下载.xls并将数据放入Excel文件

    我设法使用 VBA 达到准备从网络下载 Excel 文件的程度 但我无法弄清楚如何实际下载该文件并将其内容放入我正在使用的 Excel 文件中 有什么建议么 谢谢 这是到目前为止的代码 Sub GetData Dim IE As Inter
  • 为什么 [System.ComponentModel.ToolboxItem(false)] 默认出现在 Asp.net Web 服务中

    谁能告诉我为什么 System ComponentModel ToolboxItem false 是在Asp net Web服务中使用的吗 或许你可以在这里找到一些答案 NET API 浏览器 ToolboxItemAttribute 布尔
  • java Web应用程序中的日期转换

    String date1 13 03 2014 16 56 46 AEDT SimpleDateFormat sdf new SimpleDateFormat dd MM yyyy HH mm ss z sdf setTimeZone Ti
  • 确定网站的唯一访问者

    我正在创建一个 django 网站 使用 Apache2 作为服务器 我需要一种方法来以完整的证据方式确定我的网站 特别是每个页面 的唯一访问者数量 不幸的是 用户会有很大的动机去尝试 玩弄 跟踪系统 所以我正在努力证明这一点 有什么办法可
  • 我想将我的 NEXT.js 项目链接到静态网站

    我有一个使用 HTML CSS 开发的网站 它是一个静态网站 但现在我使用 NEXT js 与 Strapi API 集成创建了一个博客项目 我的问题是如何将我的静态网站与我的 Next js 项目链接起来 我尝试使用链接标签 但没有用 i
  • Tornado websocket handler , self.close() 正在关闭连接而不触发 on_close() 方法

    我是 python stackoverflow tornado 的新手 所以请耐心等待 纠正我 我正在使用龙卷风开发实时应用程序 当我在 Websocket 处理程序类中调用 self close 时 on close 方法不会启动 这次我
  • 从动态服务器中抓取 html 列表数据

    哈喽大家好 抱歉提出转储问题 这是我最后的手段 我发誓我尝试了无数其他 Stackoverflow 问题 不同的框架等 但这些似乎没有帮助 我有以下问题 一个网站显示一个数据列表 前面有大量的 div li span 等标签 它是一个很大的
  • 如何从网页中提取文本内容? [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我正在用java开发一个应用程序 它
  • 向下滚动时如何使图像移动?

    这是我想要实现的目标的示例 https www flambette com en https www flambette com en 我尝试过更改图像的 css 属性 但效果不能满足我的需求 我尝试过以下代码 mydocument on
  • Drupal 模板/主题资源或建议?

    我有兴趣为我正在开发的 Drupal 网站创建自定义主题 我是 Drupal 的新手 但是我在处理构建主题 CSS PHP HTML 所需的基本概念方面拥有相当多的经验 所以 我的问题是 我从哪里开始 有创建 Drupal 主题的规范指南吗
  • 我应该使用哪个命令来缩小和优化 Nodejs Express 应用程序?

    我已经准备好 Express generator sccafold 网站并需要发布它 我应该使用哪个命令来缩小文件并优化发布 另外 我应该上传哪些目录 express generator是一个基于express框架的服务端渲染框架 而不是像
  • Angular 2 RC 4“(SystemJS)无法解析[对象位置]的所有参数:”在 IE 11 中

    我的 Web 应用程序在 Chrome Firefox 和 Edge 中运行良好 但在 IE 11 中当然不行 旧版本的 IE 可能也没有 这是一个使用 Angular Cli 生成应用程序的最小应用程序 完整错误 EXCEPTION Ca
  • 获取url,给定的url重定向到

    我从 rss 链接中挖掘数据并获得一堆网址 例如 http feedproxy google com r electricpig 3 qoF8XbocUbE http feedproxy google com r electricpig 3

随机推荐

  • 万能平板刷机软件_平板电脑怎么刷机 平板电脑刷机方法【教程】

    摘要 xff1a 刷机简单说就是给平板电脑重装系统 xff0c 跟电脑重装系统一样 正常情况下 xff0c 只要硬件没有问题 xff0c 那么就99 99 可以通过刷机搞定你平板上碰到的问题 刷机真的这么神奇么 那么要怎样给平板电脑刷机呢
  • python中strftime函数_Python strftime()用法及代码示例

    在Python中 xff0c 日期和时间不是其自身的数据类型 xff0c 而是名为 strftime 函数用于将日期和时间对象转换为其字符串表示形式 它需要一个或多个格式化代码输入 xff0c 并返回字符串表示形式 用法 strftime
  • signature=cc29255b4425ca4c96b4511e5937abfa,http

    Message ID lt 458798778300 OQB26387 64 intrigue eastciti com gt MIME Version 1 0 Content Type multipart related boundary
  • php ajax等待返回,Ajax对PHP的调用未返回任何内容

    我正在尝试使我的第一个ajax示例在我的MAMP上运行 我的ajax html看起来像 xff1a 我的ajax js看起来像 xff1a 函数ajax gt gt var xmlhttp 如果 window XMLHttpRequest
  • epg信息服务器,EPG系统及EPG信息的实时更新方法

    1 一种EPG系统 包括 播出系统 1 xff0c 所述播出系统 I 包括节目单编辑模块 11 播出在线控制模块 12 和节目单网关模块 13 xff0c 所述节目单网关模块 13 根据节目单编辑模块 11 编辑的节目数据生成EPG信息 x
  • 大华服务器u盘做系统,#测评大玩家#大华P609双接口U盘轻松备份资料

    这些年随着智能手机和5G网络的普及 xff0c 很多人分享资料的时候 xff0c 都习惯使用即时聊天工具 xff0c 对于一些体积较大的文件 xff0c 则是用网盘来完成 不过现在消费者的隐私保护意识越来越高 xff0c 各种网盘服务的价格
  • coursera 计算概论与程序设计基础(李戈)-第二题

    判断闰年 正常情况下一年有365天 xff0c 但是闰年的时候 xff0c 一年有366天 现在给定一个年份 xff0c 请你判断它是不是闰年 凡是能被4整除的年是闰年 xff1b 但逢百之年 xff0c 能被4整除的并不是闰年 xff0c
  • Debian 7 安装使用 Virtualbox及增强功能

    一 安装virtualbox 可以从源里安装 sudo apt get install virtualbox 也可以下载最新版安装 https www virtualbox org wiki Downloads 二 安装增强功能 安装增强功
  • 《你必须知道的.NET》第二次印刷,未来与梦想

    你必须知道的 NET 网站 Anytao技术博客 你必须知道的 NET 第二次印刷 xff0c 未来与梦想 发布日期 xff1a 2008 11 20 作者 xff1a Anytao 2008 Anytao com xff0c Anytao
  • 51学习计划最后

    hhhhhhhhhhh 来了11111111111111111111111111111111111111111111111111111111111111111111111 555 4444 66 77 88 99 00 61 61 61 6
  • sql 跨数据库读取数据库中的数据

    跨数据库读取数据库中的数据 创建链接服务器 右键单击 连接服务器 xff0c 弹出 xff1a 点击 安全性 xff0c 弹出 xff1a 输入连接到的数据库的登陆名和密码 这样链接服务器就创建完成了 这样就可以通过链接服务器的方式查询到链
  • Android系统定制之SystemUI修改:下拉通知栏尺寸【转】

    本文转载自 xff1a https blog csdn net huil0925 article details 67632358 最近项目需要修改下拉通知栏面板的宽度 xff0c 完成后 xff0c 写个Blog做个总结 xff0c 也提
  • git只拉取github部分代码的方法

    需求 xff1a github某个项目所有代码太大 xff0c 有600 43 M xff0c 甚至更大 xff1b 只需要拉取部分代码 xff0c 一是可以降低网络消耗 xff0c 二是可以降低磁盘占用 分析了下空间占用情况 xff1a
  • MatLab计算图像圆度

    本文所述方法可以检测同一图像中的多个圆形 xff08 准确的说 xff0c 应该是闭合图像 xff09 在Matlab2010a中可以实现 附录效果图 xff1a 颗粒圆度 clear close all 读取源图像 I 61 imread
  • RSA签名的PSS模式

    本文由云 43 社区发表 作者 xff1a mariolu 一 什么是PSS模式 xff1f 1 1 两种签名方式之一RSA PSS PSS Probabilistic Signature Scheme 私钥签名流程的一种填充模式 目前主流
  • 爬虫mm131明星照片

    1 39 39 39 2 1 爬取以下站点中各个明星图片 xff0c 分别单独建文件夹存放 3 起始URL地址 xff1a http www mm131 com mingxing 4 39 39 39 5 import os 6 impor
  • 使用IDEA工具配置和运行vue项目(详细其中的坑)

    刚来公司实习发现公司的前端使用的是vue xff0c 之前根本就没有听说过 然后一上来就需要看代码 xff0c but but 就是没有文档什么的东西 xff0c 就需要自己去研读 xff0c 我就想去运行其中的前端和后端联调起来方便理解
  • pycharm永久激活方式

    网上找了好多 xff0c 还是这个最方便快捷 1 下载 链接 https pan baidu com s 1axPsIaedtZDRG7lTup9b5g 密码 7vxp xff0c 并将 JetbrainsCrack 2 10 releas
  • Majority Element出现次数超过一半的数字

    Given an array of size n find the majority element The majority element is the element that appears more than n 2 times
  • C#实现WEB服务器

    一 HTTP协议的作用原理 WWW是以Internet作为传输媒介的一个应用系统 xff0c WWW网上最基本的传输单位是Web网页 WWW的工作基于客户机 服务器计算模型 xff0c 由Web 浏览器 客户机 和Web服务器 服务器 构成