写一个简易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, )); //启动监听,并且设置一个最大的队列长度
socket.Listen();
//到这里我们的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, ));
//开始聆听你的请求
serverSocket.Listen();
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 <= )
{
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, ));
serverSocket.Listen();
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 <= )
{
break;//遇到空行了,请求结束了不用再等了
//如果不break,就一直卡在ReadLine()等着浏览器发后续的数据
}
}
}
//获取请求路径
string[] strs = firstLine.Split(' ');
//url就获取到了 类似index.html的这样的串。
string url = strs[]; 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文件就好了!!
写一个简易web服务器、ASP.NET核心知识(4)的更多相关文章
- 写一个简易浏览器、ASP.NET核心知识(3)
前言 先在文章前面说好了,省得大家发现我根本没有这样的头发,duang的一下一堆人骂我. 这篇文章的标题有点大,其实挺low的,我需要在开头解释一下.我这里只想写一个小的控制台,旨在模拟浏览器的htt ...
- 写一个简易web服务器、ASP.NET核心知识(4)--转载
第一次尝试(V1.0) 1.理论支持 这里主要要说的关于Socket方面的.主要是一个例子,关于Socket如何建立服务端程序的简单的代码. static void Main(string[] arg ...
- 自己实现一个简易web服务器
一个web服务器是网络应用中最基础的环节. 构建需要理解三个内容: 1.http协议 2.socket类 3.服务端实现原理 1.1 HTTP http请求 一般一个http请求包括以下三个部分: 1 ...
- Socket 初识 用Socket建立一个简易Web服务器
摘自<Asp.Net 本质论>作者:郝冠军 //在.Net中.system.Net命名空间提供了网络编程的大多数数据据类型以及常用操作,其中常用的类型如下: /* IPAddress 类表 ...
- Cookie详解、ASP.NET核心知识(7)
无状态的http协议 1.回顾http协议 Http协议是请求响应式的,有请求才有响应,是无状态的,不会记得上次和网页“发生了什么”. 关于http协议的这种特点,黑兔在前面的这三篇博文中进行了详细的 ...
- IIS Web 服务器/ASP.NET 运行原理基本知识概念整理 转
转http://www.cnblogs.com/loongsoft/p/7272830.html IIS Web 服务器/ASP.NET 运行原理基本知识概念整理 前言: 记录 IIS 相 ...
- 一不小心写了个WEB服务器
开场 Web服务器是啥玩意? 是那个托管了我的网站的机器么? No,虽然那个也是服务器,但是我们今天要说的Web服务器主要是指像IIS这样一类的,用于处理request并返回response的工具,没 ...
- 如何快速建立一个测试资源Web服务器及异步获取资源(Unity3D)
背景 1.最近看了几位专栏作家的文章,几篇提到了资源通过网络的动态获取.如何建立一个快速的测试环境,不免是一个问题,也就最简单的就是假设http服务器了,微软系的当然首选的IIS了,别的也能用阿帕奇或 ...
- 深入理解Tornado——一个异步web服务器
本人的第一次翻译,转载请注明出处:http://www.cnblogs.com/yiwenshengmei/archive/2011/06/08/understanding_tornado.html原 ...
随机推荐
- Websphere Application Server 环境配置与应用部署最佳实践
在发布一个运行于 WebSphere Application Server 的 J2EE 应用之前,对服务器进行配置和部署应用是必不可少的一个过程,这个过程是非常复杂的.WAS 为用户提供了可视化的管 ...
- C语言文法阅读与理解序
<指针>→* | * < 指针> <直接声明符> <标识符> | <直接声明>[]| <直接声明>[常量表达式] | < ...
- JavaScript设计模式学习之路——继承
早在学习java的时候,就已经接触了继承,在java中因为有extends关键字,因此继承就比较简单.但是在JavaScript中,只能通过灵活的办法实现类的继承. 下面是我昨天在学习过程中,了解到的 ...
- 明白JavaScript原型链和JavaScrip继承
原型链是JavaScript的基础性内容之一.其本质是JavaScript内部的设计逻辑. 首先看一组代码: <script type="text/javascript"&g ...
- Spring配置声明
<... xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="htt ...
- LBP纹理特征[转自]
LBP方法(Local binary patterns)是一个计算机视觉中用于图像特征分类的一个方法.LBP方法在1994年首先由T. Ojala, M.Pietikäinen, 和 D. Harwo ...
- BZOJ 1066:[SCOI2007]蜥蜴(最大流)
蜥蜴Description在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外. 每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到 ...
- 【bzoj5130】[Lydsy12月赛]字符串的周期 DFS+KMP
题目描述 给定 $n$ 和 $m$ ,求所有 长度为 $n$ ,字符集大小为 $m$ 的字符串,每个前缀的最短循环节长度乘积 的总和. $n\le 12,m\le 10^9$ 题解 DFS+KMP 对 ...
- 洛谷 P1972 [SDOI2009]HH的项链
不是裸题,鉴定完毕. 我是题面 对于这道题,我是离线做的... 树状数组吧,好些点 我们可以很轻易地得到一个很显然的结论,就是关于同一个数,我们只需要记录它不超过当前区间的最后一次出现的位置即可.举例 ...
- Period II FZU - 1901(拓展kmp)
拓展kmp板题 emm...我比较懒 最后一个字母进了vector两个1 不想改了...就加了个去重... 哈哈 #include <iostream> #include <cst ...