zoukankan      html  css  js  c++  java
  • 写一个简易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:UsersWinterTDesktop消息框、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服务器只是形式,而非目的!

     

    PS:刚刚发现,现在补充进来。

    不知道诸位注意到没有。

    我的web服务器,每次我从浏览器输入url发出一个请求后,服务器的控制台上都会显示两个请求。

    那么多出来的那个请求是干啥的呢?我们再仔细看一下图!

    对,没错。浏览器在请求网站图标!

    也就是说,我们想做网站图标的话,直接在网站根目录下放一个做好的

    favicon.ico文件就好了!!

     

  • 相关阅读:
    记录五年社畜萌新尝试将静态网站在docker上使用nginx部署
    C# 按照比重来随机 [搬运微调]
    前端时间戳处理去年昨天当天基于dayjs
    记录第一次亲自部署.net core 3.0坑
    .net获取/修改配置文件/web.config
    遍历实体类属性获取键值
    Linq以本周和本月为条件的Sql,Liqn查询本周,Linq查询本月
    [基础累积] C#计算时间差
    CSS3自定义滚动条样式方法
    基础的多级菜单一个没见过的思路
  • 原文地址:https://www.cnblogs.com/mcad/p/4343358.html
Copyright © 2011-2022 走看看