asp.net本质论学习笔记第一章

  早就很想看这本书了,现在终于下载了一个pdf版的,以后每天要看一些,然后做做笔记。

1,通用资源标识符(Uniform Resource Identifier, 简称"URI"),这是百度百科上的写法,书上把u写成了universal.

2,url是uri的一种,主要是指web中的统一资源定位符。

3,学习一下Uri类,下面是相关的代码:

View Code
    System.Uri ms = new Uri("http://www.cnblogs.com/wang7/admin/EditPosts.aspx?opt=1");
    Console.WriteLine("协议名:{0}", ms.Scheme);
    Console.WriteLine("主机名:{0},", ms.Host);
    Console.WriteLine("据对路径:{0}", ms.AbsolutePath);
    Console.WriteLine("端口号:{0}", ms.Port);
    Console.WriteLine("参数{0}", ms.Query);
    Console.Read();

运行结果是:

绝对路径上传到服务器后被成为虚拟路径。

4,http协议是无状态协议

(1)无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

客户端与服务器进行动态交互的Web应用程序出现之后,HTTP无状态的特性严重阻碍了这些应用程序的实现,毕竟交互是需要承前启后的,简单的购物车程序也要知道用户到底在之前选择了什么商品。于是,两种用于保持HTTP连接状态的技术就应运而生了,一个是Cookie,而另一个则是Session

(2)cookie是通过客户端保存一些值,每次请求是都将这些值发送给服务器,这样保持状态。

(3)session是通过服务器端保存一些值,每次当请求过来的时候比对一下这些值来保持状态。

5,传输层从下向上是第4层,有两个重要的协议,tcp和udp,网络编程中要用到。http是第7层应用层.网络层是第3层,有个ip协议。

socket仅仅负责传输层编程。

6,一个简单的socket服务器

View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Noesis.Javascript;
using System.Net;
using System.Net.Sockets;


namespace ConsoleTest
{
    

    class Program
    {
        static void Main(string[] args)
        {
            IPAddress ip = IPAddress.Loopback;//得到本地巡回地址127.0.0.1
            IPEndPoint point = new IPEndPoint(ip, 49155);//得到本地一个端点(ip地址:端口)
            //新建一个基于tcp和ipv4的socket
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            socket.Bind(point);//将sockey绑定到端点
            socket.Listen(10);//监听10个请求
            Console.WriteLine("开始监听端口:{0}", point.Port);
            while (true)
            {
                //开始监听,直到接收一个请求,这是一个阻塞方法
                Socket client = socket.Accept();
                Console.WriteLine(client.RemoteEndPoint);//输出客户端的地址
                byte[] buffer = new byte[2048];
                int length = client.Receive(buffer, 2048, SocketFlags.None);//接收数据
                System.Text.Encoding utf8 = Encoding.UTF8;//得到utf-8编码
                string requestString = utf8.GetString(buffer, 0, length);//将字节转为字符串
                Console.WriteLine("请求消息是:\n{0}", 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>Hello JinHe!</body></html>";//响应体
                byte[] responseBodyBytes = utf8.GetBytes(responseBody);//字符串转为字节数组

                string responseHeader = string.Format(              //响应头信息
                    "Content-Type: text/html; charset=UTF-8;\r\n Content-Length:{0}\r\n", responseBody.Length);
                byte[] responseHeaderBytes = utf8.GetBytes(responseHeader);//*******就在这个地方写成了responseBody,结果抓包发现响应头内容是响应体的内容

                client.Send(statusLineBytes);//向客户端发送状态行
                client.Send(responseHeaderBytes);//向客户端发送响应头信息
                client.Send(new byte[] { 13, 10 });//响应头和响应内容之间的分隔行,13和10就是回车换行字节
                client.Send(responseBodyBytes);//响应内容

                client.Close();//关闭连接
                if (Console.KeyAvailable)//如果按键可以使用
                {
                    break;
                }


            }
            socket.Close();//关闭套接字
        }
    }         
}

在浏览器中输入http://localhost:49155/ 则浏览器可以看到的结果。

参见:http://www.cnblogs.com/zhili/archive/2012/08/23/WebServer.html

分析:刚开始怎么都不显示响应的网页内容,在网上看到一篇相同的文档,他的显示,我一点一点的对比,调试,还是不显示,本来打算放弃了,后来看到网上说抓包看看,然后我就使用抓包工具抓包,发现响应头的内容居然是响应体,后来发现果然是在获取响应头字节时写成了获取响应体的代码。  越来越发现,抓包工具的重要行。

7,一个基于TcpListener的web服务器:

View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Noesis.Javascript;
using System.Net;
using System.Net.Sockets;


namespace ConsoleTest
{
    

    class Program
    {
        static void Main(string[] args)
        {
            IPAddress ip = IPAddress.Loopback;//得到本地巡回地址127.0.0.1
            IPEndPoint endPoint = new IPEndPoint(ip, 49155);//得到本地一个端点(ip地址:端口)

            TcpListener newServer = new TcpListener(endPoint);//新建一个监听器
            newServer.Start();//开始侦听连接请求
            while (true)
            {
                TcpClient newClient = newServer.AcceptTcpClient();//接收一个客户端请求
                Console.WriteLine("已经建立连接");
                NetworkStream ns = newClient.GetStream();//返回连接网络流
                Encoding utf8 = Encoding.UTF8;
                byte[] buffer = new byte[4096];
                int length = ns.Read(buffer, 0, 4096);//读取数据
                string requestString = utf8.GetString(buffer, 0, length);//得到请求的字符串
                Console.WriteLine("请求消息是:\n{0}", 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>Hello JinHe!</body></html>";//响应体
                byte[] responseBodyBytes = utf8.GetBytes(responseBody);//字符串转为字节数组

                string responseHeader = string.Format(              //响应头信息
                    "Content-Type: text/html; charset=UTF-8;\r\n Content-Length:{0}\r\n", responseBody.Length);
                byte[] responseHeaderBytes = utf8.GetBytes(responseHeader);//*******就在这个地方写成了responseBody,结果抓包发现响应头内容是响应体的内容

                ns.Write(statusLineBytes, 0, statusLineBytes.Length);
                ns.Write(responseHeaderBytes, 0, responseHeaderBytes.Length);
                ns.Write(new byte[] { 13, 10 },0,2);//记住,响应头和响应体之间一定要有换行,否则响应体不会显示
                ns.Write(responseBodyBytes, 0, responseBodyBytes.Length);

                ns.Close();

                if (Console.KeyAvailable)
                {
                    break;
                }
            }
            newServer.Stop();//关闭            
       
        }
    }         
}

这个例子要记住:响应头和响应体之间一定要加一个换行,否则响应体不会显示。

 8,基于HttpListener的web服务器:

View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Noesis.Javascript;
using System.Net;
using System.Net.Sockets;


namespace ConsoleTest
{
    

    class Program
    {
        static void Main(string[] args)
        {


            if (!HttpListener.IsSupported)
            {
                throw new InvalidOperationException("只用windos sp2或server 2003以上版本可以使用HttpListener");
            }

            //一定在末尾加斜杠
            string[] prefixes = new string[] { "http://localhost:49115/"};

            HttpListener listener = new HttpListener();

            foreach (string s in prefixes)
            {
                listener.Prefixes.Add(s);//设施uri前缀
            }
            listener.Start();//开始监听
            while (true)
            {
                HttpListenerContext context = listener.GetContext();//得到传入的请求
                HttpListenerRequest request = context.Request;//得到http请求
                Console.WriteLine("Method:{0};RawUrl:{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("Pragram:{0}", request.Headers["Pragram"]);

                HttpListenerResponse response = context.Response;//得到响应对象
                string responseBody = "<html><head><title>From Socket Server</title></head><body>Hello JinHe!</body></html>";//响应体
                response.ContentLength64 = Encoding.UTF8.GetByteCount(responseBody);//响应内容长度
                response.ContentType = "text/html;charset=utf-8";//响应内容
                System.IO.Stream stream = response.OutputStream;//响应输出流
                System.IO.StreamWriter writer = new System.IO.StreamWriter(stream);//写入流
                writer.Write(responseBody);
                writer.Close();
                if (Console.KeyAvailable)
                {
                    break;
                }
               
            }
            listener.Stop();      
       
        }
    }         
}

 9,应用程序域:这是一个比进程小的单元,让一个程序运行的逻辑空间。

一个进程有多个应用程序域,每一个应用程序域中承载一个.NET可执行程序,应用程序域为承载的应用程序提供了深度隔离。如果进程中一个应用程序域失败了,其他的应用程序域也能保持正常。

 asp.net将网站应用程序寄宿在一个独立的应用程序域中,以便于管理。

10

GAC:global assembly cache

他的作用是可以存放一些有很多程序都要用到的公共Assembly,例如System.Data、System.Windows.Forms等等。这样,很多程序就可以从GAC里面取得Assembly,而不需要再把所有要用到的Assembly都拷贝到应用程序的执行目录下面。举例而言,如果没有GAC,那么势必每个WinForm程序的目录下就都要从C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705下面拷贝一份System.Windows.Forms.dll,这样显然不如都从GAC里面取用方便,也有利于Assembly的升级和版本控制。

11,System.Web.HttpRuntime类是整个asp.net服务器处理的入口。

每一个应用程序域中都存在这样一个类。它的静态方法ProcessRequest帮助我们开始请求的

处理。只要将HttpWorkerRequest对象传递给这个方法,就可以开始服务器的请求处理了。

(1)请求参数的对象类型HttpRequest,这个类提供了有关请求的属性和方法。

(2)响应参数的对象类型HttpResponse,这个类提供有关响应的属性和方法。

12(1)对于最后一个例子,asp.net服务器,如果要使用AplicationHost.CreateApplicationHost

创建应用程序域,则需要将第一个参数hostType的程序集拷贝到网站的bin目录下,否则报告错误

找不到文件。

(2)CreateApplicationHost的第三个参数需要改为网站目录;

运行之后要在浏览器地址栏中输入:http://localhost:49152/     然后才可以输出请求信息。

对于类WebServer,它是一个应用程序域,对于他真正的作用我还是不明白,在那个方法里加断点就是不会执行这个类的方法。迷惑????

结束语:

原文地址:https://www.cnblogs.com/wang7/p/2710958.html