在学习的过程中总要经历一些痛苦的过程才能达到想要达到的地方。前几天牛人给我出了一道题,说是让我写一段程序判断一个网站的服务器是否正常运行。本着我自己先仔细研究实在不行再问的原则我各种郁闷了好几天。
各种没头绪,虽然磕磕绊绊的找到了一个网址http://zhoufoxcn.blog.51cto.com/792419/561934
但是各种看不懂不理解啊。
在看了好久实在是不理解之后,我求助了。牛人说,我需要先了解Http协议的基本原理。
第一站 HTTP协议
打开浏览器—>在地址栏中输入URL—>看到了网页。 原理是怎样的呢?
输入URL后—>浏览器给Web服务器发送了一个Request –->Web服务器接到Request后进行处理,生成相应的Response—>服务器发送Response给浏览器—>浏览器解析Response中的HTML –>看到了网页
URL(Uniform Resource Locator) 地址用于描述一个网络上的资源, 基本格式如下
schema://host[:port#]/path/.../[;url-params][?query-string][#anchor]
scheme 指定低层使用的协议(例如:http, https, ftp)
host HTTP服务器的IP地址或者域名
port# HTTP服务器的默认端口是80,这种情况下端口号可以省略。如果使用了别的端口,必须指明,例如 http://www.cnblogs.com:8080/
path 访问资源的路径
url-params
query-string 发送给http服务器的数据
anchor- 锚
URL 的一个例子
http://www.mywebsite.com/sj/test;id=8079?name=sviergn&x=true#stuffSchema: http
host: www.mywebsite.com
path: /sj/test
URL params: id=8079
Query String: name=sviergn&x=true
Anchor: stuff
更多具体内容详见http://kb.cnblogs.com/page/130970/ 非常实用
HTTP是一个无状态的面向连接的协议,无状态不代表HTTP不能保持TCP连接,更不能代表HTTP使用的是UDP协议(无连接)。
从HTTP/1.1起,默认都开启了Keep-Alive,保持连接特性,简单地说,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。
Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。
HTTP/1.1中定义了5类状态码, 状态码由三位数字组成,第一个数字定义了响应的类别
1XX 提示信息 - 表示请求已被成功接收,继续处理
2XX 成功 - 表示请求已被成功接收,理解,接受
3XX 重定向 - 要完成请求必须进行更进一步的处理
4XX 客户端错误 - 请求有语法错误或请求无法实现
5XX 服务器端错误 - 服务器未能实现合法的请求
第二站 开写
现在大致能看懂http://zhoufoxcn.blog.51cto.com/792419/561934里面的大概结构了,但是由于还是不太理解所以还是局限在这个程序的代码结构中。后来牛人跟我说,写程序不是目的,知道他们的互相关系才是真正的目的。期间也走了很多弯路,比如说问了别的小牛人同学,结果发现小牛人同学由于太聪明了,她的思维模式我完全无法理解,她跟我说:只要知道原理数据结构之类的就够了,其他的代码就从网上抄过来。这样避免你自己写产生的错误。可是我想跟她说:童鞋,我连原理都不理解啊。所以还要回到自己的老路研究之前的那个网页,从而找到怎么写的。一开始我做了一个网页,因为我以前做过,我也会这个,所以我设计了一个输入textbox 然后点击按钮就会显示结果。彻彻底底被牛人否了,让我直接在console里面实现。原因是他不会asp.net。好吧,你说了算。还好这个我会。so新建一个console form然后。我在结合了小牛人给的代码和之前网页的代码的时候发现了一个突破口。HttpStatusCode 这个可以显示出来状态代码。这是一个枚举类型。里面罗列出来了网页的的状态。但是怎么也没法结合起来用。
小牛人给的代码:
string ExpectedResultBadrequest = HttpStatusCode.BadRequest.ToString();
后来找到了这两个网页,终于可以磕磕绊绊的写出来了。而且最终发现可以用很简单的实现出来。不用像网页的那么复杂。
http://msdn.microsoft.com/zh-cn/library/system.net.httpwebresponse.statuscode.aspx
以下为最终结果:
using System.Net;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.baidu.com");//(HttpWebRequest)是强制类型转换,(HttpWebRequest)是一种WebRequest所以可以利用转换进行使用。
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Console.WriteLine(response.StatusCode.ToString());
Console.ReadLine();//HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create("https://www.google.com/");
//HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
//Console.WriteLine(myHttpWebResponse.StatusCode.ToString());
//Console.ReadLine();
}
}
}
下一站:获取response的内容-牛人的新作业
Stream receiveStream = response.GetResponseStream();
Encoding encode = System.Text.Encoding.GetEncoding("UTF-8");
StreamReader readStream = new StreamReader(receiveStream,encode);
Console.WriteLine("\r\nResponse stream received");
char[] read = new char[256];
int count = readStream.Read(read,0,256);
Console.WriteLine("HTML...\r\n");
while (count > 0)
{
string str = new string(read, 0, count);
Console.Write(str);
count = readStream.Read(read, 0, 256);
}
Console.WriteLine("");
response.Close();
readStream.Close();
Console.ReadLine();
说明readStream.Read 的意思是从数据流中往buffer里面读取网页数据,每次读一小段,当没有数据往外读取的时候就为0了。