用Socket来简单实现IIS服务器
刚刚接触ASP.NET编程,为了更好的屡清楚服务器的处理过程,就用Socket模拟服务器来处理请求。用Socket来模拟服务器的时候,同样是自己来封装一些对应的类文件。包括 HttpRequest、HttpResponse、HttpContext、HttpApplication、IHttpHandel。主要的执行流程是:先用Socket来创建一个简单的服务器,进行监听,当监听到请求后将请求交给处理程序去处理,应用程序中根据请求的是静态资源还是动态资源做出不同的处理。然后通过Socket对象将响应类容给发送回去。这只是为了更好的了解服务器的处理,进行了一个简单的模拟,程序中有很多的bug,但是能够实现基本的功能
HttpRequest类
主要包含几个主要的属性:请求方式,请求地址,请求协议的版本号
public class HttpRequest
{
public HttpRequest (string str)
{
if (string.IsNullOrEmpty(str))
{
return;
}
string head = str.Replace("\r\n", "$").Split('$')[];
string[] heads = head.Split(' ');
Method = heads.Length>? heads[]:"";
//得到请求的绝对路径
Url = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), heads.Length>? heads[].Substring():heads[]);
Protocol = heads.Length > ? heads[] : ""; } public string Method { get; set; }
public string Url { get; set; }
public string Protocol { get; set; }
}
HttpRequest类
HttpResponse类
包含响应头和响应体,在网络上传输的是二进制文件,故将这两个属性定义为byte[],中间还包含其他的一些属性。其中响应长度是动态的,在处理程序里面设置
public class HttpResponse
{
public HttpResponse (HttpRequest request)
{
this.request = request;
Type = GetType(Path.GetExtension(request.Url));
} private HttpRequest request;
private string Type { get; set; }
public int Length { get; set; }
public byte[] Head {
get
{ // -----响应报文------------
//HTTP/1.1 200 OK
//Connection: keep-alive
//Date: Thu, 26 Jul 2007 14:00:02 GMT
//Server: Microsoft-IIS/6.0
//X-Powered-By: ASP.NET
//Content-Length: 190
//Content-Type: text/html
//Set-Cookie: ASPSESSIONIDSAATTCSQ=JOPPKDCAMHHBEOICJPGPBJOB; path=/
//Cache-control: private
////--空行--
//响应体(正文) StringBuilder sb = new StringBuilder();
sb.AppendFormat("{0} {1}\r\n", request.Protocol, "200 OK");
sb.AppendLine("Date:" + DateTime.Now.ToString());
sb.AppendLine("Server:QIGANG-PC");
sb.AppendLine("Content-Length:" + Length);
sb.AppendLine("Content-Type:" + Type);
sb.AppendLine();
return Encoding.UTF8.GetBytes(sb.ToString()); }
}
public byte[] Body { get; set; } ///根据请求来得到响应的类型
private string GetType (string ext)
{
string type1 = "text/html;charset=utf-8";
switch (ext)//mime-type
{
case ".aspx":
case ".html":
case ".htm":
type1 = "text/html;charset=utf-8";
break;
case ".png":
type1 = "image/png";
break;
case ".gif":
type1 = "image/gif";
break;
case ".jpg":
case ".jpeg":
type1 = "image/jpeg";
break;
case ".css":
type1 = "text/css";
break;
case ".js":
type1 = "application/x-javascript";
break;
default:
type1 = "text/plain;charset=gbk";
break;
}
return type1;
}
}
HttpResponse类
HttpContext类
在这个类里面简单的封装了两个成员对象,就是HttpRequest和HttpResponse两个成员,其它的就从简了
public class HttpContext
{
public HttpContext (string str)
{
Request = new HttpRequest(str);
Response = new HttpResponse(Request);
}
public HttpRequest Request { get; set; }
public HttpResponse Response { get; set; }
}
HttpContext类
IHttpHandel接口
由于在客户端请求的数据中可能请求的是一个动态网页,这是就需要交给.NET Framework 来进行处理,为了方便处理,故要求所有的动态网页都需要实现一个接口,只有实现了这个接口的程序才能够被浏览器给请求到
public interface IHttpHandel
{
void ProcessRequest (HttpContext context);
}
IHttpHandel接口
服务器端Socket程序
在这主要是启动一个Socket对象,来进行连接的监听,然后把监听到的对象交给处理程序 HttpApplication进行处理
private void button1_Click (object sender, EventArgs e)
{
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), ));
socket.Listen();
Thread thread = new Thread((obj) =>
{
Socket server = obj as Socket;
while (true)
{
Socket client = server.Accept();
Thread cth = new Thread((obj2) =>
{
Socket cSocket = obj2 as Socket; byte[] by = new byte[cSocket.Available];
cSocket.Receive(by, , by.Length, SocketFlags.None);
//拿到请求头文件
string str = Encoding.UTF8.GetString(by); /*--------- 调用请求处理函数进行处理 ---------*/
HttpContext context = new HttpContext(str);
HttpApplication app = new HttpApplication(context, cSocket);
});
cth.IsBackground = true;
cth.Start(client);
}
});
thread.IsBackground = true;
thread.Start(socket);
}
Socket服务端程序
HttpApplication类
这个类需要传递一个参数,上下文对象。然后进行请求的解析,根据请求的是静态资源还是动态资源去进行不同的处理。如果是静态资源就直接冲磁盘文件中读取返回,如果是动态资源,就交给对应的类。当然前提是请求的资源名称就对应了一个类文件。
public class HttpApplication
{
//构造函数
public HttpApplication (HttpContext context,Socket socket)
{
string url =context.Request.Url;
if(string.IsNullOrEmpty(url)){
return;
}
string ext = Path.GetExtension(url);
//请求的是动态资源文件
if (ext == ".aspx")
{
//下面的代码中也就没有进行错误的处理了,主要是模拟,没有考虑其他的情况
//拿到请求资源的文件名(不包含后缀)
string cs = Path.GetFileNameWithoutExtension(url);
//得到当前程序的程序集
Assembly ass = Assembly.GetExecutingAssembly();
//拿到请求的文件对应的类
Type type = ass.GetType(ass.GetName().Name + "." + cs, true, true);
//创建对象,进行调用
IHttpHandel handel = Activator.CreateInstance(type) as IHttpHandel;
handel.ProcessRequest(context);
//上面几句话可以合并到一起,拿到程序集后直接CreateInstance();
}
else if (ext == ".ashx")
{
}
else//访问静态资源
{
//直接从磁盘中读取请求的资源文件
byte[] by = File.ReadAllBytes(url);
context.Response.Length = by.Length;
context.Response.Body = by; }
socket.Send(context.Response.Head);
socket.Send(context.Response.Body);
}
}
HttpApplication类
整个请求的模型基本上就差不多完成了,如果是请求的动态文件b.aspx,那么这个b.cs文件需要实现IHttpHandel接口,同时在规定的方法里面进行处理,代码如下:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace IIS_Two
{
public class b:IHttpHandel {
public void ProcessRequest (HttpContext context)
{
//读取模板HTML文件
string html = File.ReadAllText("temp.html");
string temp = "<table border='1'>{0}</table>";
//读取文本文件类容,拼接一个table表格
using (StreamReader reader = new StreamReader("1.txt"))
{
string str = "";
List<string> list = new List<string>();
while ((str = reader.ReadLine()) != null)
{
string[] strs = str.Split(':');
list.Add("<tr><td>" + strs[] + "</td><td>" + strs[] + "</td></tr>"); }
temp = string.Format(temp, string.Join("", list));
}
//模板内容的替换
html = html.Replace("$body", temp);
byte[] by = Encoding.UTF8.GetBytes(html);
context.Response.Length = by.Length;
context.Response.Body = by;
}
}
}
b.cs文件,对应b.aspx资源
附上b.cs中用到的一个HTML模板和一个txt文件
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
$body
</body>
</html>
temp.html
aaa:22
bbb:23
ccc:18
1.txt
整个简单的模拟就完成了,bug很多,这不重要。如果请求一个简单的html页面或者是jpg等图片都能够成功,当然这些文件要存在代码中所写的目录下面才行
用Socket来简单实现IIS服务器的更多相关文章
- Socket 实现简单的多线程服务器程序
**********服务器端************* public class ServerSocket{ public static void main(String[] args) throws ...
- 第27篇 重复造轮子---模拟IIS服务器
在写程序的时候,重复造轮子是程序员的一个大忌,很多人对重复造轮子持有反对的态度,但是我觉得这个造轮子的过程,是对于现有的知识的一个深入的探索的过程,虽然我们不可能把轮子造的那么的完善,对于现在有的东西 ...
- 运用socket实现简单的服务器客户端交互
Socket解释: 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket. Socket的英文原义是“孔”或“插座”.作为BSD UNIX的进程通信机制,取后一种意 ...
- Visual Studio写的项目在 IIS 服务器上运行的两种简单方法
首先需要PC上开启了IIS服务,相关方法网上很多,也很简单 第一种:直接在项目中操作 1.创建一个项目,然后右击选中项目,右击,单击属性,打开项目属性标签页面 如图,选择Web标签,在服务器栏目中选中 ...
- IIS服务器简单搭建
概况 系统:WIN10企业版 开发工具:VS2013 - VS2017 IIS版本:IIS6.0 安装 安装步骤如图: 这里需要注意一点信息服务器下默认web管理工具只有iis控制台勾上了,也就意味 ...
- 第37章 socket编程 之练习:实现简单的web服务器
一.参考网址 1.linux C学习之实现简单的web服务器 2.C语言实现简单Web服务器(一)
- 自己动手模拟开发一个简单的Web服务器
开篇:每当我们将开发好的ASP.NET网站部署到IIS服务器中,在浏览器正常浏览页面时,可曾想过Web服务器是怎么工作的,其原理是什么?“纸上得来终觉浅,绝知此事要躬行”,于是我们自己模拟一个简单的W ...
- socket.io简单入门(一.实现简单的图表推送)
引子:随着nodejs蓬勃发展,虽然主要业务系统因为架构健壮性不会选择nodejs座位应用服务器.但是大量的内部系统却可以使用nodejs试水,大量的前端开发人员转入全堆开发也是一个因素. 研究本例主 ...
- 20145216 20145330 《信息安全系统设计基础》 实验五 简单嵌入式WEB 服务器实验
20145216 20145330 <信息安全系统设计基础> 实验五 简单嵌入式WEB 服务器实验 实验报告封面 实验步骤 1.阅读理解源码 进入/arm2410cl/exp/basic/ ...
随机推荐
- 堆和索引堆的实现(python)
''' 索引堆 ''' ''' 实现使用2个辅助数组来做.有点像dat.用哈希表来做修改不行,只是能找到这个索引,而需要change操作 还是需要自己手动写.所以只能用双数组实现. #引入索引堆的核心 ...
- python中从内部循环直接跳出多层循环
学习循环的时候碰到一道题,需要从内部循环中直接跳出所有循环,想了很久终于想到一种好办法(小白认知) 题目为:使用while循环输出100-50,从大到小,到50时,再循环输出0-50,从小到大. ex ...
- NOIP2017提高组day2T1题解(奶酪)
题目链接:奶酪 这道题还是很水的,在下拿了满分. 并没有用什么高级的算法,我讲一下基本思路. 我们把每个洞都视为一个节点. 我们读入相关数据后,就先进行预处理,通过每个节点的信息和题目的规定,建立一张 ...
- day06作业---字典循环
'''1.1使⽤循环打印以下效果: ***************''' for a in range(1,6): print(a*'*') '''1.2: ***** **** *** ** * ' ...
- 2018.10.29 bzoj4564: [Haoi2016]地图(仙人掌+莫队)
传送门 根据原图建一棵新的树. 把原图每一个环上除了深度最浅的点以外的点全部向深度最浅的点连边. 然后可以搞出来一个dfsdfsdfs. 这个时候我们就成功把问题转换成了对子树的询问. 然后就可以对权 ...
- Win7 VS2017简单编译FFMPEG播放器FFPlay
Win平台简单编译FFPlay播放器,顺便纪念下雷霄骅,一年前刚学FFMPEG时还看过他的博客,昨晚再次搜FFMPEG文章时才知道人已经走了... 做成了视频放到B站 https://www.bili ...
- adb push init.rc /
http://blog.csdn.net/jumper511/article/details/28856249 修改Android init.rc文件后,需要将修改后的文件上传到手机,但是发下如下问题 ...
- Nginx使用(配置开机启动)
环境: 系统:CentOS 6.5 Final 安装目录:/usr/local/nginx Nginx开机自启: ①编写shell实现控制 vi /etc/init.d/nginx 添加内容: #!/ ...
- MFC源码实现文件对照表
CDocManager类[实现文件] /SRC/DOCTEMPL.CPP CSingleDocTemplate类[实现文件] /SRC/DOCSINGL.CPP CWinApp::OnFileOpen ...
- Docker Swarm集群部署
一.系统环境 1)服务器环境 节点名称 IP 操作系统 内核版本 manager 172.16.60.95 CentOs7 4.16.1-1.el7.elrepo.x86_64 node-01 172 ...