我想任何IT人都熟悉HTTP协议,每个人都可以解释它。但如果我问你HTTP协议的请求方式有哪些? POST 和GET 有什么区别? GET 或POST 发送的数据大小有限制吗? HTTP 响应的状态是什么?那么如何在C# 中使用它呢?如果您不能清楚地回答其中大部分问题,那么这篇文章就是为您准备的!概要如下:
1.HTTP概述
1.1. HTTP协议的客户端和服务器端交互
1.2. HTTP消息
1.3. HTTP请求方式
1.4. HTTP 响应代码
2. 抓包分析
3.POST和GET的区别
4.用一个例子来说明如何在C#中使用POST、GET等操作
4.1.HttpWeb请求
4.2. HttpWeb响应
4.3.编写WinForm程序,打开博客园主页(附源码)
1.HTTP概述
为了唤醒您对HTTP协议的记忆或者让您了解HTTP协议,首先简单介绍一下HTTP协议。超文本传输协议(HTTP) 是Internet 上使用最广泛的网络协议。所有WWW 文件都必须符合此标准。 HTTP 最初设计的目的是提供一种发布和接收HTML 页面的方法。
HTTP 的发展是万维网联盟和互联网工程任务组合作的结果,最终发布了一系列RFC,其中最著名的是RFC 2616。RFC 2616 定义了当前广泛使用的HTTP 版本协议,——HTTP 1.1。
1.1. HTTP协议的客户端和服务器端交互
HTTP 是客户端和服务器端请求和响应(TCP) 的标准。客户端是最终用户,服务器是网站。客户端通过浏览器、网络爬虫等工具向服务器的指定端口(默认端口为80)发起HTTP请求。 (我们称之为客户端)调用用户代理。响应服务器存储HTML 文件和图像等资源。 (我们称)该响应服务器为源服务器。用户代理和源服务器之间可能存在多个中间层,例如代理、网关或隧道。尽管TCP/IP 协议是Internet 上最流行的应用程序,但HTTP 协议并不强制要求使用它以及(基于)它支持的层。事实上,HTTP 可以通过任何其他Internet 协议或其他网络来实现。 HTTP 仅假设可靠的传输(由其底层协议提供),并且可以使用任何可以提供此类保证的协议。
通常,HTTP客户端发起请求,与服务器的指定端口(默认为80端口)建立TCP连接。 HTTP 服务器在该端口上侦听客户端发送的请求。收到请求后,服务器会向客户端发送回状态行,例如“HTTP/1.1”
200 OK"和(响应)消息。消息的消息体可以是请求的文件、错误消息或者其他信息。
HTTP使用TCP而不是UDP的原因是(打开一个)网页必须传输大量数据,而TCP协议提供传输控制、数据按顺序组织和纠错。通过HTTP 或HTTPS 协议请求的资源由统一资源标识符(或更准确地说,URI)标识。
客户端和服务器端的结构和交互过程可以用下面两张图来表示:
图1 Web客户端-服务器结构(Web服务器的超文本链接通过网站上的链接跳转到其他服务器)
图2. Web 客户端和服务器之间的交互
1.2. HTTP消息
客户端和服务器之间的交互使用两种类型的消息:请求和响应。
HTTP请求的格式为:
图3. HTTP 请求的格式
HTTP 响应的格式为:
图4. HTTP 响应格式
从上面可以看出,HTTP请求和响应消息的头部包含了可变数量的字段,并且使用空行将所有头部字段与消息体分开。标头字段由字段名称、后跟冒号、空格和字段值组成。字段名称不区分大小写。
消息头可以分为三类:一类用于请求,一类用于响应,一类用于描述正文。有一些标头(例如:日期)可以在请求和响应中使用。描述主题的标头可以出现在POST 请求和所有响应消息中。 HTTP的头部字段如下所示:
图5. HTTP 标头字段
1.3. HTTP请求方式
HTTP/1.1协议总共定义了八种方法(有时称为“动作”)来指示Request-URI指定的资源的不同操作模式:
选项
返回服务器对特定资源支持的HTTP 请求方法。您还可以通过向Web 服务器发送“*”请求来测试服务器的功能。
头
向服务器请求与GET请求一致的响应,只不过不会返回响应体。该方法允许您获取响应标头中包含的元信息,而无需传输整个响应内容。
得到
向特定资源发出请求。注意: GET 方法不应该用在会产生“副作用”的操作中,例如在Web 应用程序中。原因之一是GET可能会被网络蜘蛛等随机访问。
邮政
向指定资源提交数据以处理请求(例如提交表单或上传文件)。数据包含在请求正文中。 POST 请求可能会导致创建新资源和/或修改现有资源。
放
将其最新内容上传到指定资源位置。
删除
请求服务器删除Request-URI标识的资源。
痕迹
服务器收到的echo请求,主要用于测试或诊断。
连接
HTTP/1.1 协议是为可以更改管道连接的代理服务器保留的。
方法名称区分大小写。当请求所针对的资源不支持相应的请求方法时,服务器应返回状态码405(Method Not allowed);当服务器无法识别或不支持相应的请求方法时,应返回状态码501(未实现)。
HTTP 服务器至少应该实现GET 和HEAD 方法,其他方法是可选的。另外,除了上述方法外,特定的HTTP服务器还可以扩展自定义方法。
安全方法
开发人员应该意识到他们的软件代表用户在互联网上进行交互,并且应该告知用户他们正在采取的操作可能会对自己或他人产生意想不到的重要影响。
特别是对于GET 和HEAD 方法,这些请求除了获取资源信息之外不应该有任何其他含义。也就是说,这些方法应该被认为是“安全的”,这意味着该操作用于获取信息而不是修改信息。客户应使用其他“非安全”方法,例如POST、PUT和DELETE,以特殊方式(通常是按钮而不是超链接)让客户意识到可能的责任(例如按钮引起的资金交易)或被告知所请求的操作可能不安全(例如,文件将被上传或删除)。
但是,不能理所当然地认为服务器不会在没有任何副作用的情况下处理GET 请求。事实上,许多动态资源都具有此功能。这里的重要区别是用户没有请求此副作用,因此不应对这些副作用负责。
幂等方法
如果不考虑错误或过期等问题,多个请求的副作用与单个请求相同或根本没有副作用,那么这些请求方法可以被认为是“幂等”的。 GET、HEAD、PUT 和DELETE 方法都具有此类幂等属性。另外,根据协议,OPTIONS和TRACE不应该有副作用,因此它们也是幂等的。
如果由多个请求组成的请求序列的结果在重复执行该请求序列或任何一个或多个请求后没有改变,则该请求序列是“幂等的”
的。然而,可能会发生由多个请求组成的请求序列是“非幂等的”,即使在该请求序列中执行的所有请求方法都是幂等的。例如,此请求序列的结果取决于将在该序列的下一次执行期间修改的变量。
1.4. HTTP 响应代码
服务器程序响应的第一行称为状态行。状态行以HTTP 版本号开头,后跟3 位响应代码,最后是人类可读的响应短语。根据第一个位置,响应可以分为5 类:
图6. HTTP 响应代码
2. 抓包分析
现在我们基本了解了HTTP。接下来我使用wireshark捕获我打开博客园主页时我的电脑与博客园服务器交互的HTTP数据包。做好准备,关闭一些可能干扰我们爬取和打开博客园的相关程序。如下图所示,当我们在浏览器中输入www.cnblogs.com并确认时,首先捕获以下包:
图7. 打开博客园抓到的包
从图中可以看出,当我们在浏览器中输入www.cnblogs.com并确认时,就会向服务器发送一条HTTP请求消息:GET/HTTP/1.1。根据1.2中介绍的HTTP报文格式,我们知道GET对应的是request,/对应的是request-line,HTTP/1.1对应的是版本号。除了请求行之外,还发送了一些头字段,如:Accept、Accept-Language、User-Agent、Accept-Encoding、Host、Connection等,并且可以看到它们的格式为:头字段名称:字段值。请注意,冒号后面有一个空格。
接下来我们看一下GET/HTTP/1.1请求的响应消息:
图8. GET/HTTP/1.1请求的响应消息
响应消息的状态行为:HTTP/1.1 200 OK,其中HTTP/1.1对应版本号,200对应response-code,OK对应response-phrase。除了状态行之外,还返回一些头字段,例如:Cache-Control、Content-Type、Content-Encoding、Expires、Last-Modified、Vary、Server 等(从上图可以看出,博客使用IIS7.0)
上面捕获的数据包是一个GET包。现在看一个POST数据包——,打开博客园首页时,通过POST请求获取左侧的分类信息。
图9. POST 数据包
我们可以看到POST /ws/PublicUserService.asmx/GetLoginInfo HTTP/1.1。除了将GET替换为POST外,其他信息类似。让我们放大看一下发送的标头字段:
图10. POST /ws/PublicUserService.asmx/GetLoginInfo HTTP/1.1 的标头字段
注意:这里我不会解释本节涉及的一些头字段。我想此时大家应该对HTTP有了更深入的了解。
3.POST和GET的区别
1.3中介绍了8种方法,其中GET和POST是最基本也是最常用的。表单提交中get和post方法的区别总结如下:
GET是从服务器获取数据,POST是向服务器传输数据。
GET 将参数数据队列添加到提交表单的ACTION 属性指向的URL 中。这些值对应于表单中的每个字段,并且可以在URL 中看到。 POST 通过HTTP
POST机制将表单中的每个字段及其内容放置在HTML HEADER中,并将其传输到ACTION属性指向的URL地址。用户无法看到此过程。
对于GET方法,服务器端使用Request.QueryString来获取变量的值。对于POST方法,服务器端使用Request.Form来获取提交的数据。
GET传输的数据量较小,不能大于2KB(这主要是由于URL长度限制)。 POST传输的数据量较大,默认情况下一般不限制。但理论上,该限制取决于服务器的处理能力。
GET 不太安全,POST 更安全。因为GET在传输过程中,数据是放在请求的URL中的。如今,许多现有的服务器、代理服务器或用户代理都会将请求URL记录到日志文件中,然后放在某个地方,因此可能会有一些私人信息被第三方看到。另外,用户还可以直接在浏览器上看到提交的数据,一些内部系统消息也会显示在用户面前。所有POST 操作对用户都是不可见的。
提交FORM时,如果没有指定Method,则默认为GET请求(.net默认为POST)。表单中提交的数据将附加到url 中,与url 之间用? 分隔。字母数字字符按原样发送,但空格会转换为“+”符号,其他符号会转换为%XX,其中XX 是符号的十六进制ASCII(或ISO Latin-1)值。 GET请求提交的数据放在HTTP请求协议头中,而POST提交的数据放在实体数据中; GET提交的数据最多只能是2048字节,而POST则没有这个限制。 POST传递的参数在doc中,是http协议传递的文本。接受时会解析参数部分。获取参数。一般情况下使用POST比较好。 POST隐式提交数据,GET在URL中传递,用于传递一些不需要保密的数据。 GET 是在URL 中传入参数,而POST 则不是。
注:关于“POST和GET的区别”,我在网上查了高人的资料。由于找不到出处,而且到处都有转发,所以这里就不贴出相关网址了。你可以在百度或谷歌上找到它。
4.用一个例子来说明如何在C#中使用POST、GET等操作
在介绍例子之前,我们首先要介绍一下HttpWebRequest和HttpWebResponse。在C#中,这两个类用于实现客户端向服务器发送HTTP消息以及客户端接受服务器的HTTP响应。
4.1.HttpWeb请求
在设计实现示例之前,我们首先要引入HttpWebRequest类。 —— 提供了WebRequest 类的HTTP 特定实现。 HttpWebRequest 类提供对WebRequest 中定义的属性和方法的支持,并且还提供使用户能够使用HTTP 直接与服务器交互的附加功能。支持属性和方法。
不要使用HttpWebRequest 构造函数。使用System.Net.WebRequest.Create 方法初始化新的HttpWebRequest 对象。如果统一资源标识符(URI) 的方案为http://或https://,则Create 返回HttpWebRequest 对象。
HTTP 消息的标头字段在HttpWebRequest 中表示为公共属性。下表列出了由属性或方法设置或由系统设置的HTTP 标头。
如果本地计算机配置指定使用代理,或者请求指定代理,则使用代理发送请求。如果未指定代理,则请求将发送到服务器。
HttpWebRequest类主要包含以下与HTTP服务器交互的方法:
中止:取消对Internet 资源的请求。
AddRange:向请求添加范围标头。
BeginGetRequestStream:开始对用于写入数据的Stream 对象的异步请求。
BeginGetResponse:启动对Internet 资源的异步请求。
创建:初始化一个新的WebRequest。 (继承自WebRequest。)
CreateDefault:为指定的URI 方案初始化新的WebRequest 实例。 (继承自WebRequest。)
CreateObjRef:创建一个对象,其中包含生成与远程对象通信的代理所需的所有相关信息。 (继承自MarshalByRefObject。)
EndGetRequestStream:结束对用于写入数据的Stream对象的异步请求。
EndGetResponse:结束对Internet 资源的异步请求。
GetRequestStream:获取用于写入请求数据的Stream对象。
GetResponse:返回来自Internet 资源的响应。
GetSystemWebProxy:返回当前模拟用户的Internet Explorer 设置中配置的代理。 (继承自WebRequest。)
InitializeLifetimeService:获取控制该实例的生命周期策略的生命周期服务对象。 (继承自MarshalByRefObject。)
RegisterPrefix:为指定的URI 注册WebRequest 后代。 (继承自WebRequest。)
4.2. HttpWeb响应
在设计实现示例之前,我们还需要引入HttpWebRequest类。 —— 提供了WebResponse 类的HTTP 特定实现。此类包含对WebResponse 类中属性和方法的HTTP 特定使用的支持。 HttpWebResponse 类用于生成发送HTTP 请求和接收HTTP 响应的HTTP 独立客户端应用程序。
注意
不要将HttpWebResponse 与HttpResponse 类混淆;后者用于ASP.NET 应用程序,其方法和属性通过ASP.NET 的内部Response 对象公开。
切勿直接创建HttpWebResponse 类的实例。相反,请使用通过调用HttpWebRequest.GetResponse 返回的实例。您必须调用Stream.Close 方法或HttpWebResponse.Close 方法来关闭响应并释放连接以供重用。不必同时调用Stream.Close 和HttpWebResponse.Close,但这样做不会导致错误。
从Internet 资源返回的公共标头信息作为此类的属性公开。完整列表请参见下表。可以从Headers 属性中以名称/值对的形式读取其他标头。下表显示了可通过HttpWebResponse 类的属性获得的公共HTTP 标头。
通过调用GetResponseStream 方法,以Stream 的形式从Internet 资源返回响应内容。
HttpWebRequest类主要包含以下与HTTP服务器交互的方法:(与HttpWebRequest类相比,方法较少)
CreateObjRef:创建一个对象,其中包含生成与远程对象通信的代理所需的所有相关信息。 (继承自MarshalByRefObject。)
GetLifetimeService:检索控制该实例的生命周期策略的当前生命周期服务对象。 (继承自MarshalByRefObject。)
GetResponseHeader:获取随响应返回的标头的内容。
GetResponseStream:获取用于从服务器读取响应正文的流。
InitializeLifetimeService:获取控制该实例的生命周期策略的生命周期服务对象。 (继承自MarshalByRefObject。)
4.3.编写WinForm程序,打开博客园主页(附源码)
通过前两节的介绍,我们对HttpWebRequest类以及HttpWebRequest类有了一定的了解。现在我们将应用它们来编写一个小程序进行练习。程序界面大致如下:
功能也比较简单,就是通过点击“在WebBrowser中显示”按钮,博客主页就会显示在下面的WebBrowser控件中。点击“查看HTML源代码”按钮,会弹出一个对话框,显示博客主页的html源代码。
首先我们介绍一下如何实现——。通过点击“查看html源代码”按钮,会弹出一个对话框,显示博客首页的html源代码。核心代码如下:
点击“查看html源代码”按钮,会弹出一个对话框,显示博客首页的html源代码。
其实这个过程的效果如果我们在浏览器中进入博客园网站打开的话是一样的,只不过这里我们是通过HttpWebRequest类和HttpWebRequest类的对象来实现的。
不过,通过点击“在WebBrowser中显示”按钮,与下面在WebBrowser控件中显示博客主页的功能类似,只不过是在WebBrowser控件中显示,并且我将一些常用的HTTP相关操作封装到了命名空间中。 Helper,以备将来之用,本质同上。点击下载整个项目的源码。
我的源码还是比较简单的。它只是实现了使用HttpWebRequest类和HttpWebRequest类与HTTP服务器进行交互。更完善的功能期待您来完成。
补充说明:关于URL的长度限制,IE的URL最多可以是2083个字符(半角),而GET最多只能是2048个字符。然而,RFC 2616,超文本传输协议——HTTP/1.1,不限制URL的最大长度。
参考:写这篇文章的时候,我看了很多文章。我将列出给我印象最深的那些。
维基百科(HTTP),http://zh.wikipedia.org/zh-cn/HTTP
MSDN(HttpWebRequest),http://msdn.microsoft.com/zh-cn/library/8y7x3zz2%28v=VS.80%29.aspx
MSDN(HttpWebResponse),http://msdn.microsoft.com/zh-cn/library/system.net.httpwebresponse%28VS.80%29.aspx
TCP/IP协议详解第3卷
作者:吴勤
【HTTP协议基础:POST与GET操作差异解析及C#应用实践】相关文章:
2.米颠拜石
3.王羲之临池学书
8.郑板桥轶事十则
用户评论
终于学习到HTTP协议了!感觉以前很多东西都没搞明白了。
有11位网友表示赞同!
我一直以为POST和GET都是一样的。。。原来不同啊!
有11位网友表示赞同!
这篇文章内容挺详细的,看得懂C#代码也很重要。
有13位网友表示赞同!
想做web开发的话,HTTP协议是基础知识啊!
有17位网友表示赞同!
最近在做API整合,感觉了解这些操作方法很实用。
有19位网友表示赞同!
希望后面还有其他关于网络编程的文章,我很想多了解!
有19位网友表示赞同!
C#学习资料少啊,这篇文章挺难得的。
有12位网友表示赞同!
POST和GET的区别确实很重要,要注意哪些场景用哪个比较好!
有17位网友表示赞同!
以后开发的时候可以参考一下这篇教程,提高代码质量。
有20位网友表示赞同!
文章的解释很清楚,容易理解!
有17位网友表示赞同!
这个C#代码示例写的很好,方便学习。
有16位网友表示赞同!
感谢作者分享这些知识,帮了我的忙!
有13位网友表示赞同!
感觉HTTP协议挺复杂的,需要慢慢积累经验啊...
有5位网友表示赞同!
如果能再详细点解释下错误处理部分更好!
有8位网友表示赞同!
这篇文章让我对网络编程有了更清晰的认识。
有11位网友表示赞同!
打算以后自己尝试写一个简单的web项目!
有5位网友表示赞同!
原来HTTP协议还有这么多的细节,涨姿势了!
有17位网友表示赞同!
希望作者可以继续分享更多高级知识!
有14位网友表示赞同!
看了这篇文章,对网络安全也有一点了解了。
有6位网友表示赞同!
学习编程真的需要不断地积累和实践!
有13位网友表示赞同!