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

前言

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

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

没错,今天要尝试的东西,是自己写一个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会有这样的一个提示。点允许就好了。

从上面例子看,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自动回互般的,高冷的一直回答说:“哎呀,你好,你好!”。

改进(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页面。成功的显示出来了!

结束感言

(表示我很开心)

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

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

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

不知道诸位注意到没有。

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

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

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

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

favicon.ico文件就好了!!

时间: 2024-12-23 06:31:26

写一个简易web服务器、ASP.NET核心知识(4)的相关文章

写一个简易浏览器、ASP.NET核心知识(3)

前言 先在文章前面说好了,省得大家发现我根本没有这样的头发,duang的一下一堆人骂我. 这篇文章的标题有点大,其实挺low的,我需要在开头解释一下.我这里只想写一个小的控制台,旨在模拟浏览器的http通信. 不是真的能用的浏览器. 简单的说,今天的全部工作就是 建立Socket→发送请求报文→ 服务器返回报文→显示报文.仅此而已喏. 实话说出来,是不是一下就low了? 我的目的只有两个. 1.加深对http协议的理解   2.深化对B/S结构的认识. 如果您已经非常了解这些东西了.那就甭搭理我

Socket 初识 用Socket建立一个简易Web服务器

摘自<Asp.Net 本质论>作者:郝冠军 //在.Net中.system.Net命名空间提供了网络编程的大多数数据据类型以及常用操作,其中常用的类型如下:/*IPAddress 类表示一个IP地址* IPEndPoint类用来表示一个IP地址和一个端口号的组合,成为网络的端点.* System.Net.Sockets命名空间中提供了基于Socked编程的数据类型.* Socket类封装了Socked的操作.* 常见的操作:* Listen:设置基于连接通信的Socket进入监听状态,并设置等

TinyWS —— 一个C++写的简易WEB服务器(一)

写在前面 每个码农可能都会偶尔有自己做一个常用软件的想法,比如操作系统,编译器,邮件服务器/客户端,文字编辑器等等.这里面有些很难,比如操作系统,做一个最简单的也要付出很大的努力,可是大部分常用工具都是可以比较容易的做一个简易版本(当然也是只能玩玩而已).于是我做了一个非常简陋的WEB服务器 —— TinyWS.这里主要是记录下自己整个过程中的一些想法. TinyWS是用C++”从头开始“做的,也就是说,除了C/C++的标准库和操作系统的系统调用,并没有使用第三方库.我并不喜欢C++(甚至有些厌

TinyWS —— 一个C++写的简易WEB服务器(三)

写在前面 代码已经托管在 https://git.oschina.net/augustus/TinyWS.git 可以用git clone下来.由于我可能会偶尔做一些修改,不能保证git 库上的代码与blog里的完全一致(实际上也不可能把所有的代码都贴在这里).另外,TinyWS是基于linux写的(ubuntu 14.10 + eclipse luna,eclipse工程我也push到了git库),故在Windows上可能无法正常编译(主要是系统调用 部分可能会不同). 前面的内容可参考上一篇

TinyWS —— 一个C++写的简易WEB服务器(二)

写在前面 代码已经托管在 https://git.oschina.net/augustus/TinyWS.git 可以用git clone下来.由于我可能会偶尔做一些修改,不能保证git 库上的代码与blog里的完全一致(实际上也不可能把所有的代码都贴在这里).另外,TinyWS是基于linux写的(ubuntu 14.10 + eclipse luna,eclipse工程我也push到了git库),故在Windows上可能无法正常编译(主要是系统调用 部分可能会不同). 前面的内容可参考上一篇

深入理解Tornado——一个异步web服务器

本人的第一次翻译,转载请注明出处:http://www.cnblogs.com/yiwenshengmei/archive/2011/06/08/understanding_tornado.html原文地址:http://golubenco.org/?p=16 这篇文章的目的在于对Tornado这个异步服务器软件的底层进行一番探索.我采用自底向上的方式进行介绍,从轮巡开始,向上一直到应用层,指出我认为有趣的部分.所以,如果你有打算要阅读Tornado这个web框架的源码,又或者是你对一个异步we

自己写浏览器和web服务器的分析!

自己写浏览器和web服务器 在android写一个浏览器 editText:输入网址ip:port/login.html,提交 把域名解析成ip 产生请求行 get login.html /r/n 产生请求头 user-agent:/r/n host: new socket(ip,port).println(行,头) ip[tcp[行,头]]在网络上传输到达服务器了, 自己写一个web服务器 new serverSocket(8080) 我程序拿到是tcp中的数据 get login.html

《用Java写一个通用的服务器程序》01 综述

最近一两年用C++写了好几个基于TCP通信类型程序,都是写一个小型的服务器,监听请求,解析自定义的协议,处理请求,返回结果.每次写新程序时都把老代码拿来,修改一下协议解析部分和业务处理部分,然后就一个新的程序就诞生了.如此这般做了几回,就萌生了一个想法:是不是可以做一个通用的服务器程序,每次只要实现很少的代码就可以构建的一个新的服务器程序? 巧的是在用C++写代码的时候,我刚好碰到过一个叫做Push Framework的开源项目(在这里可以找到:www.pushframework.com),就是

Java实现一个简易HTTP服务器 (二) -- 多线程

Java实现一个简易HTTP服务器 (二) -- 多线程 运行方法:新建项目后在目录下创建index.html. favicon为可选项,作为网站图标 public class Server { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(80); System.out.println("Server started at &quo