你的位置:首页 > ASP.net教程

[ASP.net教程]写一个简易web服务器、ASP.NET核心知识(4)


前言


昨天尝试了,基于对http协议的探究,我们用控制台写了一个简单的浏览器。尽管浏览器很low,但是对于http协议有个更好的理解。

clipboard说了上面这一段,诸位猜到我要干嘛了吗?(其实不用猜哈,标题里都有,又都不瞎。。。我就是调侃一下,说些没营养的笑话。我认为这样能不那么枯燥,尽管不好笑吧,但这不重要!)

没错,今天要尝试的东西,是自己写一个web服务器。初衷依旧和昨天一样,旨在理解一些东西,而不是真的写出一个多牛的东西。

 

第一次尝试(V1.0)


1.理论支持

其实关于http协议的理论方面我在《写一个浏览器》的博文中已经说过了,这里不再累述了。

这里主要要说的关于Socket方面的。主要是一个例子,关于Socket如何建立服务端程序的简单的代码掩饰。

 

    static void Main(string[] args)    {      //创建一个新的Socket,这里我们使用最常用的基于TCP的Stream Socket(流式套接字)      var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);      //将该socket绑定到主机上面的某个端口      socket.Bind(new IPEndPoint(IPAddress.Any, 4530));      //启动监听,并且设置一个最大的队列长度      socket.Listen(4);      //到这里我们的Socket已经运行起来了,但仅仅是运行起来,什么都不会做的!      Console.WriteLine("Server is ready!");      Console.Read();    } 

打开调试一口,因为要监听某个端口,windows会有这样的一个提示。点允许就好了。

clipboard[1]

 

从上面例子看,socket的职责仅仅是监听4530端口,什么都不会做的!

就像一个人的耳朵。他会聆听,但是不会倾诉。职责所限,我们需要一个监听4530端口的耳朵。

但是从交流的角度看,web服务器仅仅能聆听是不够的。

请求来了以后(监听到请求以后),我还需要一个既能聆听,又能诉说的Socket。去和请求交流。

刚刚那个socket为啥不能直接交流呢? 不不不,他得继续去聆听新的请求。

2.说说思路

这次实验的主要思路是这样的。

1)监听4530端口

2)当请求来了以后,我们使用Socket socket = serverSocket.Accept();建立一个新的socket。

3)新的socket返回一个字符串给请求方! 

完了(读liao)。

也就是说,我们v1.0版本的web服务器,不管你如何请求,他都会返回你同一个字符串!(任性吧?其实我挺喜欢就这样的。)

3.代码 

static void Main(string[] args){      //我仅负责聆听,因为你来了,我就得接着等待下一个。      //(据说注释写成这样的都是妖精!工作时候这样写能被打死不?等我找着工作了我试试)      Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);      //绑定监听的端口      serverSocket.Bind(new IPEndPoint(IPAddress.Any, 8070));      //开始聆听你的请求      serverSocket.Listen(10);      while (true)      {        Console.WriteLine("等着请求");        //没有请求的状态下,程序就在这里停留。        //你来了,serverSocket就会把你的心愿告诉给一个新的socket。程序就继续执行了!(哎呀,文艺)        Socket socket = serverSocket.Accept();        Console.WriteLine("来了请求");        using (NetworkStream stream = new NetworkStream(socket))        using (StreamReader reader = new StreamReader(stream))        {          string line;          while ((line = reader.ReadLine()) != null)          {            Console.WriteLine(line);            if (line.Length <= 0)            {              break;//遇到空行了,请求结束了不用再等了              //如果不break,就一直卡在ReadLine()等着浏览器发后续的数据            }          }        }               using (NetworkStream stream = new NetworkStream(socket))        using (StreamWriter writer = new StreamWriter(stream))        {          writer.WriteLine("HTTP/1.1 200 OK");          writer.WriteLine();          writer.WriteLine("哎呀,你好,你好!");        }        socket.Disconnect(false);      }}

4.调试

我们就这样任性的、如qq自动回互般的,高冷的一直回答说:“哎呀,你好,你好!”。

clipboard[2]

改进(V2.0)


1.改进需求

上一个版本的web服务器(姑且这么叫着。)根本没有一点web服务器的样子。聊天嘛,总不能一直“呵呵”下去。会没朋友的!

所以新的web服务器改进需求如下。

1.能够获取请求 路径

2.能够根据请求路径对应的文件,返回响应的静态页面!

好歹有个正经人家孩子的样子嘛,老“呵呵”,成何体统。

我们话不多说,直接开始敲代码吧!

2.实现

static void Main(string[] args){      Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);      serverSocket.Bind(new IPEndPoint(IPAddress.Any, 8080));      serverSocket.Listen(10);      while (true)      {        Console.WriteLine("等着请求");        Socket socket = serverSocket.Accept();        Console.WriteLine("来了请求");        string firstLine;        using (NetworkStream stream = new NetworkStream(socket))        using (StreamReader reader = new StreamReader(stream))        {          //想1.0版本里多出了这么一句。          //想想http请求报文格式吧,第一行有文件路径的喏!          firstLine = reader.ReadLine();          string line;          while ((line = reader.ReadLine()) != null)          {            Console.WriteLine(line);            if (line.Length <= 0)            {              break;//遇到空行了,请求结束了不用再等了              //如果不break,就一直卡在ReadLine()等着浏览器发后续的数据            }          }        }        //获取请求路径        string[] strs = firstLine.Split(' ');        //url就获取到了 类似index.html的这样的串。        string url = strs[1];        Console.WriteLine("url=" + url);        using (NetworkStream stream = new NetworkStream(socket))        using (StreamWriter writer = new StreamWriter(stream))        {          //为什么要指定绝对路径呢?想想正常web服务器里的【物理路径】是啥意思。应该就懂了。          string filePath = @"C:\Users\WinterT\Desktop\消息框、JBar" + url;          Console.WriteLine("filePath=" + filePath);          if (File.Exists(filePath))          {            writer.WriteLine("HTTP/1.1 200 OK");            writer.WriteLine();            string html =            File.ReadAllText(filePath);            Console.WriteLine(html);            writer.Write(html);          }          else          {            writer.WriteLine("HTTP/1.1 404 NOT FOUND");            writer.WriteLine();            writer.Write("404,没有找到");          }        }        socket.Disconnect(false);      }}

3.调试

请求的是我电脑里已有的一个html页面。成功的显示出来了!

clipboard[3]

 

结束感言


clipboard[4]clipboard[5]clipboard[6]clipboard[7](表示我很开心)

其实这次实验,得出的结论依然是http协议是请求/响应式的。传递的是文本!

就这个软件而言,还有很多需要改进的地方。 但这不是重点。重点是理解一些东西,做web服务器只是形式,而非目的!