1.统一资源标示符

  1) 格式:协议://主机[.端口号][绝对路径[?参数]],在Http://www.kencery.com/hyl/index/login中,http表示协议的名称,www.kencery.com表示主机的地址,可选的端口号没有出现,那么,将使用http协议的默认端口号80,绝对路径为:hyl/index/login,如果没有提供绝对路径,那么,使用默认的绝对路径/。

  2) .NET中提供的对URL或者URI操作的方法代码如下:  

 Uri uri = new Uri("https://www.kencery.com/hyl/index/login");
Console.WriteLine(uri.Scheme); //协议的名称 输出结果:https
Console.WriteLine(uri.Host); //取得Uri地址中的主机部分 输出结果:www.kencery.com
Console.WriteLine(uri.Port); //端口号 输出结果:80
Console.WriteLine(uri.AbsolutePath); //绝对路径 输出结果:/hyl/index/login
Console.WriteLine(uri.Query); //地址中的参数部分 输出结果:
Console.ReadLine();

  3) 浏览器要找到我们访问的服务器,需要提供服务器的网络地址,在当前的TCP/IP协议下,所谓的服务器地址其实就是一个IP地址,目前我们使用的是IPV4的地址,每个地址由四个字节共32位组成,理论上讲,可以表示4G的网络地址,微软的IP地址是:207.46.19.254,所以我们直接在地址栏中输入http://207.46.19.254也可以看到微软的网站。

  4)HTTP协议

    1.当浏览器寻找到Web服务器的地址之后,浏览器将帮助我们把对服务器的请求转换为一系列的参数发送给Web服务器,服务器收到浏览器发来的请求参数之后,将会分析这些数据并进行处理,然后向浏览器回应处理的结果,也就是一些新的数据,浏览器收到之后,就会解析这些数据,并将他们显示在浏览器中。

    2,在浏览器与Web服务器之间进行通信的时候,需要双方都要能够理解的规范进行通讯,这种程序之间进行通信的语言规范,我们称之为协议,协议有许多种,根据国际标准化组织ISO的网络参考模型,程序与程序之间的通信可以分为7种,从低到高依次是:物理层,数据链路层,网络层,传输层,会话层,表示层,应用层,每层都有自己对应的协议。

    3.请求微软网站的请求信息如图所示:Http请求

2.最简单的Web服务器

  2.1 网络插座Socket

    在Unix时代,为了解决传输层的编程问题,Unix提供了类似于文件操作的网络操作方式—Socket,通过Socket,开发人员可以像操作文件一样通过打开,写入,读取,关闭等操作来完成网络编程,Socket不负责应用层的协议,仅仅负责传输层的协议。

    当通过Socket开发网络应用程序的时候,首先需要考虑所使用的网络类型,主要包括以下三个方面:

    1)Socket类型,使用网络协议的类别,IPV4的类型为PF_INET

    2)数据通信的类型,常见的数据报(Sock_DGRAM),数据流(SOCK_STREAM)。

    3)使用网络协议,比如:TCP协议。

  2.2 在.NET中,System.Net命名空间提供了网络编程的大多数数据类型以及常用操作,其中类型如下:

    1) IPAddress类用来表示一个IP地址

    2) IPEndPoint类用来表示一个IP地址和一个端口号的组合,成为网络的端口。

    3) System.NET.Sockets命名空间中提供了基于Socket编程的数据类型。

    4) Socket类封装了Socket的操作。常见的操作如下:

      a) Listen:设置基于连接通信的Socket进入监听状态,并设置等待队列的长度。

      b) Accept:等待一个新的连接,当新连接到达的时候,返回一个针对新连接的Socket对象。通过这个新的Socket对象,可与新连接通信。

      c) Receive:通过Socket接收字节数据,保存到一个字节数组中,返回实际接收的字节数。

      d)  Send:通过Socket发送预先保存在字节数组中的数据。

  2.3 通过Socket编程创建一个简单地Web服务器

 private static void Main(string[] args)
{
//取得本机的loopbakack网络地址,即127.0.0.1
IPAddress address = IPAddress.Loopback;
//创建可以访问的端点,49152表示端口号,如果设置为0,表示使用一个空闲的端口号
IPEndPoint endPoint = new IPEndPoint(address, );
//创建Socket,使用IPV4地址,传输控制协议TCP,双向,可靠,基于连接的字节流
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//将Socket绑定到一个端口上
socket.Bind(endPoint);
//设置连接队列的长度
socket.Listen();
Console.WriteLine("开始监听:端口号:{0}", endPoint.Port);
while (true)
{
//开始监听,这个方法会阻塞线程的执行,直到接收到一个客户端的连接请求
Socket client = socket.Accept();
//输出客户端地址
Console.WriteLine("客户端地址:{0}", client.RemoteEndPoint);
//准备读取客户端请求的地址,读取的数据将保存在一个数组中
byte[] buffer = new byte[];
//接收数据
int length = client.Receive(buffer, , SocketFlags.None);
//将请求的数据翻译成UTF-8
Encoding utf8 = Encoding.UTF8;
string requestString = utf8.GetString(buffer, , length);
//显示请求的信息
Console.WriteLine(requestString);
//回应的状态行
string statusLine = "HTTP/1.1 200 OK\r\n";
byte[] statusLineBytes = utf8.GetBytes(statusLine);
//准备发送到客户端的网页
string responseBody =
"<html><head><title>From Socket Server</title></head><body><h1>Hello,World</h1></body></html>";
byte[] responseBodyBytes = utf8.GetBytes(responseBody);
//回应的头部
string responseHeader = string.Format("Content-type:text/html;charset=UTF-8\r\nContent-Length:{0}\r\n",
responseBody.Length);
byte[] responseHeaderBytes = utf8.GetBytes(responseHeader);
//向客户端发送状态信息
client.Send(statusLineBytes);
//向客户端发送回应头
client.Send(responseBodyBytes);
//头部和内容的分割行
client.Send(new byte[] {, });
//向客户端发送内容部分
client.Send(responseBodyBytes);
//断开与客户端的链接
client.Close();
if (Console.KeyAvailable)
{
break;
}
     }
54      //关闭服务器
55 socket.Close();
 }

  2.4 基于TcpListener的Web服务器

    为了简化基于TCP协议的监听程序,.NET在System.Net.Sockets命名空间中提供了TcpListener类,代码如下:

 private static void Main(string[] args)
{
//取得本机的loopbakack网络地址,即127.0.0.1
IPAddress address = IPAddress.Loopback;
//创建可以访问的端点,49152表示端口号,如果设置为0,表示使用一个空闲的端口号
IPEndPoint endPoint = new IPEndPoint(address, );
//创建Socket,使用IPV4地址,传输控制协议TCP,双向,可靠,基于连接的字节流
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//将Socket绑定到一个端口上
socket.Bind(endPoint);
//设置连接队列的长度
socket.Listen();
Console.WriteLine("开始监听:端口号:{0}", endPoint.Port);
while (true)
{
//开始监听,这个方法会阻塞线程的执行,直到接收到一个客户端的连接请求
Socket client = socket.Accept();
//输出客户端地址
Console.WriteLine("客户端地址:{0}", client.RemoteEndPoint);
//准备读取客户端请求的地址,读取的数据将保存在一个数组中
byte[] buffer = new byte[];
//接收数据
int length = client.Receive(buffer, , SocketFlags.None);
//将请求的数据翻译成UTF-8
Encoding utf8 = Encoding.UTF8;
string requestString = utf8.GetString(buffer, , length);
//显示请求的信息
Console.WriteLine(requestString);
//回应的状态行
string statusLine = "HTTP/1.1 200 OK\r\n";
byte[] statusLineBytes = utf8.GetBytes(statusLine);
//准备发送到客户端的网页
string responseBody =
"<html><head><title>From Socket Server</title></head><body><h1>Hello,World</h1></body></html>";
byte[] responseBodyBytes = utf8.GetBytes(responseBody);
//回应的头部
string responseHeader = string.Format("Content-type:text/html;charset=UTF-8\r\nContent-Length:{0}\r\n",
responseBody.Length);
byte[] responseHeaderBytes = utf8.GetBytes(responseHeader);
//向客户端发送状态信息
client.Send(statusLineBytes);
//向客户端发送回应头
client.Send(responseBodyBytes);
//头部和内容的分割行
client.Send(new byte[] {, });
//向客户端发送内容部分
client.Send(responseBodyBytes);
//断开与客户端的链接
client.Close();
if (Console.KeyAvailable)
{
break;
}
}
//关闭服务器
socket.Close();
}

  2.5 基于HttpListener的web服务器

    为了进一步简化HTTP协议的监听器,.NET在命名空间System.Net中提供了HttpListener类,伴随这个对象,.NET提供了一系列相关对象封装了HTTP的处理工作,注意,这个类使用Http.sys系统组件来完成工作,所以,只有在Windows XP SP2或者Server2003以上的操作系统中磁能使用。

 private static void Main(string[] args)
{
//检查系统是否支持
if (!HttpListener.IsSupported)
{
throw new System.InvalidOperationException("使用HTTPListener必须为Windows XP SP2或者Server 2003以上系统");
}
//注意前缀必须以/正斜杠结尾
string[] prefixes = new string[] {"http://localhost:49125/"};
//创建监听器
HttpListener listener = new HttpListener();
//增加监听的前缀
foreach (string s in prefixes)
{
listener.Prefixes.Add(s);
}
//开始监听
listener.Start();
Console.WriteLine("监听中。。。。。。");
while (true)
{
//注意:GetContext方法将阻塞线程,直到请求到达
HttpListenerContext context = listener.GetContext();
//取得请求对象
HttpListenerRequest request = context.Request;
Console.WriteLine("{0}{1} HTTP/1.1", request.HttpMethod, request.RawUrl);
Console.WriteLine("Accept:{0}", string.Join(",", request.AcceptTypes));
Console.WriteLine("Accept-Language:{0}", string.Join(",", request.UserLanguages));
Console.WriteLine("User-Agent:{0}", request.UserAgent);
Console.WriteLine("Accept-Encoding:{0}", request.Headers["Accept-Encoding"]);
Console.WriteLine("Connection:{0}", request.KeepAlive ? "Keep_Alive" : "close");
Console.WriteLine("Host:{0}", request.UserHostName);
Console.WriteLine("Pragma:{0}", request.Headers["Pragma"]);
//取得回应的对象
HttpListenerResponse response = context.Response;
//构造回应内容
string responseString =
@"<html><head><title>From Socket Server</title></head><body><h1>Hello,World</h1></body></html>";
//设置回应头部内容,成都,编码
response.ContentLength64 = Encoding.UTF8.GetByteCount(responseString);
response.ContentType = "text/html;chrset=UTF-8";
//输出回应内容
Stream output = response.OutputStream;
StreamWriter writer = new StreamWriter(output);
writer.Write(responseString);
//必须关闭输出流
writer.Close();
if (Console.KeyAvailable)
{
break;
}
}
//关闭服务器
listener.Close();
Console.ReadLine();
}

  上面三个关于简单地模拟了一下Web服务器的实例,实现结果如图所示:

  

ASP.NET本质论第一章网站应用程序学习笔记1的更多相关文章

  1. ASP.NET本质论第一章网站应用程序学习笔记3-对象化的Http

    在.NET环境下,万物皆对象,在HttpRuntime收到请求之后,立即将通过HttpWorkerRequest传递的参数进行分析和分解,创建方便用于网站应用程序处理用的对象,其中主要涉及到两个对象类 ...

  2. ASP.NET本质论第一章网站应用程序学习笔记2

    1.初步走进ASP.NET 上篇笔记我们讲述了服务器监听问题,这篇我们就要讲述具体的请求处理了,ASP.NET所涉及的类大多数定义在System.Web程序集中. 在.NET中,程序集管理的最小逻辑单 ...

  3. ASP.NET本质论第二章应用程序对象学习笔记1

    1.请求的处理参数—上下文对象HttpContext 1) 针对每一次请求,ASP.NET将创建一个处理这次请求所使用的HttpContext对象实例,这个对象实例将用来在ASP.NET服务器的处理过 ...

  4. 0001-20180421-自动化第一章-python基础学习笔记

    ======================学习python==================介绍: python种类: cpython(*),jpython,ironpython,rubypyth ...

  5. 01.第一章_C++ Primer学习笔记_开始

    1.2 初始输入输出 iostream库里面包含两个基础类型istream和ostream,分别表示输入流和输出流,一个流就是一个字符序列,从IO设备读出或者写入IO设备. 标准的输入输出对象 标准库 ...

  6. C语言编程入门之--第一章初识程序

    第一章 初识程序 导读:计算机程序无时不刻的影响着人类的生活,现代社会已经离不开程序,程序的作用如此巨大,那么程序到底是什么呢?本章主要讨论程序的概念,唤起读者对程序的兴趣,同时对C语言程序与其它语言 ...

  7. 《算法》第一章部分程序 part 2

    ▶ 书中第一章部分程序,加上自己补充的代码,包括简单的计时器,链表背包迭代器,表达式计算相关 ● 简单的计时器,分别记录墙上时间和 CPU 时间. package package01; import ...

  8. 《算法》第一章部分程序 part 1

    ▶ 书中第一章部分程序,加上自己补充的代码,包括若干种二分搜索,寻找图上连通分量数的两种算法 ● 代码,二分搜索 package package01; import java.util.Arrays; ...

  9. windows核心编程-第一章 对程序错误的处理

    第一章-对程序错误的处理 在开始介绍Microsoft Windows 的特性之前,必须首先了解 Wi n d o w s的各个函数是如何进行错误处理的. 当调用一个Wi n d o w s函数时,它 ...

随机推荐

  1. POJ 3903 Stock Exchange

    Stock Exchange Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2954   Accepted: 1082 De ...

  2. 打开jnlp Faild to validate certificate, the application will not be executed.

    今天连jenkins, 本来好好的,只是我在一台机器上一直不断的启动不同的jnlp,绑定不同命名的slave, 然后突然就报错了, 如下截图所示:

  3. 转载 jquery $(document).ready() 与window.onload的区别

    Jquery中$(document).ready()的作用类似于传统JavaScript中的window.onload方法,不过与window.onload方法还是有区别的. 1.执行时间 windo ...

  4. Web services 安全 - HTTP Basic Authentication

    根据 RFC2617 的规定,HTTP 有两种标准的认证方式,即,BASIC 和 DIGEST.HTTP Basic Authentication 是指客户端必须使用用户名和密码在一个指定的域 (Re ...

  5. java--实现将文字生成二维码图片,并在中间附上logo,下方附上文字

    前段时间因为工作需要,要实现将一段文字或者url生成二维码,然后中间附上logo,下方正中间附上文字的功能. 上网找了几篇教程学习了下,由于没有保存借鉴的博文链接,所以就没po上参考文章的链接啦,感谢 ...

  6. Go Go

    Go Go *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important ...

  7. DDD:两篇不错的文章

    文章列表 Coding for Domain-Driven Design: Tips for Data-Focused Devs. Strengthening your domain: Aggrega ...

  8. DDD:建模原语 之 四象图(转载的神文)

    “模型.状态和行为特征.场景”和“四象图”,建模观的命名与立象. 建模原语:四象图 作者:achieveidea@gmail.com 命名:模型.结构特征.行为特征.场景(及其规约). 释义:模型,描 ...

  9. 解决msgfmt无法使用的问题

    参考: http://blog.sina.com.cn/s/blog_4fb490ff0100csne.html http://linux.die.net/man/1/msgfmt http://pa ...

  10. MySQL中的账号与权限管理

    MySQL权限管理 权限系统的工作原理     MySQL权限系统通过下面两个阶段进行认证:     (1)对连接的用户进行身份认证,合法的用户通过认证.不合法的用户拒绝连接.     (2)对通过认 ...