网页的请求与响应均通过HTTP来完成,HTTP是Web最重要的基础核心。
HttpWebRequest与HttpWebResponse通过HTTP协议,完成网络“请求/响应”模型架构所需的功能,同时存取网页上各种特定元素。
一、HTTP通信协议
HTTP组成格式主要包含http标题及http主体,这两个部分请求与响应的消息有差别。
客户端向服务器端所发出的HTTP请求消息,其标题包含了一些重要的信息如:
(同样服务器响应客户端也会有消息,也有头部信息)
Server:Microsoft-IIS/5.0
Content-Location:http://www.nantay.com.tw/Default.htm
Date: Sun, 02 Nov 2003 16:37:09 GMT
Content-Type: text/html
Accept-Ranges: bytes
Last-Modified: Sat, 30 Aug 2003 09:03:22 GMT
ETag: "50f5f90d56ec31:da0
Content-Length: 5985
一个客户端的HTTP请求标题主要由几个连续的字符串消息列组成,每一列开头的关键词代表一种特定的消息种类,紧接着冒号连接其相关信息,比较重要的信息项目如:
Referer:
标记客户端上一次浏览过的网页URI,建立网页快取机制,方便整理捜寻重新浏览过的网页。
User-Agent:
提供服务器端当前客户端所使用的系统平台、软件版本,这个信息可以让服务器端针对特定用户端,提供所需的服务。
Accept:
代表客户端计算机当前所支持的MIME格式类型,每种类型以一个斜线链接主类与子类,若是其类表示式为“*/*”,表示客户端接收任何类的MIME格式。
Content-Type:
表示响应的数据格式,此例为text/html。
Server:
表示服务器的系统平台,此例为“Microsoft-IIS/5.0”。
Date:
消息建立的时间。
二、使用 HttpWebRequest 与 HttpWebResponse
HttpWebRequest与HttpWebResponse分别衍生自 WebRequest 及WebResponse这两个抽象基类。
使用方法同前面一样:
首先引用WebRequest类Create()方法,建立一个WebRequest对象,传入HTTP协议的URI标头,接下来将其形成HttpWebRequest类的对象,再利用此HttpWebRequest对象,便可取得所需的数据流及服务器返回的网页内容。
HttpWebRequest对象引用GetResponse()方法,返回HttpWebResponse对象,再由GetResponseStream方法,取得包含HTTP响应消息的数据流,解析其中的字节数据,就从中将整个网页数据一一取出。
三、解析网页
HttpWebRequest与HttpWebResponse类最大的用途,在于提供解析HTTP消息所需的方法与属性成员。
HttpWebRequest类定义为数不少的属性成员,这些成员包含足以让应用取得HTTP消息的相关信息,例如标题、联机信息及Cookie等, Headers属性的定义如下:
Public Property Headers As WebHeaderCollection
结果返回一个组成HTTP标头的“键/值”配对集合的WebHeaderCollection类对象。
对WebHeaderCollection集合型对象,可以直接引用ToSting()将其内容转换成为字符串输出,或是使用For Each语法,将其中各标头信息取出。
所有的属性成员分为两大类,其中一种是设置或读取http的标头值,如Accept、ContentType及ContentType等;
另外一类则是存取与送出的HTTP消息指定的相关特性,如 KeepAlive、RequestUri 及 CookieContainer 等。
标头值属性列表(HTTP标头消息)
属性项目 说 明
Accept HTTP标头头值Accept的读写
ContentLength HTTP标头值Content-length的读写
ContentType HTTP标头值Content-type的读写
Expect HTTP标头值Expect的读写
Headers 取得HTTP标头的“名称/值”配对集合
UserAgcnt HTTP标头值User-agent的读写
HTTP相关属性列表
属性项目 说 明
Address 取得实际回显请求的因特网资源URI
Connection 取得或设置连接HTTP标头的值
CookieContainer 取得或设置与要求相关的Cookie
KeepAlive 指示是否与连接的因特网资源建立持续联机
Method 方法
RequestUri 取得要求的原始URI
SendChunked 指示传送至因特网资源的数据是否分区段进行
Headers 属性由客户端 HTTP 堆栈而不是浏览器 HTTP 堆栈支持。
如果应用程序不将客户端 HTTP 堆栈用于 HTTP 响应,并尝试获取子类中的 Headers 属性,则引发 NotImplementedException。
SupportsHeaders 属性可用于确定 Headers 属性是否在不需要处理异常的情况下受到支持。
Imports System.Net
Public Class Form1
Private Sub btnGet_Click(sender As Object, e As EventArgs) Handles btnGet.Click
Dim hwq As HttpWebRequest
Dim hwp As HttpWebResponse
Dim colHeader As WebHeaderCollection
hwq = CType(HttpWebRequest.Create(txtAddress.Text), HttpWebRequest) '创建对象
hwp = hwq.GetResponse
colHeader = hwp.Headers '取得响应头
txtHeader.Text = colHeader.ToString
txtOther.Text = "获取最后修改时间: " & hwp.LastModified.ToString & vbCrLf &
"获取响应的方法: " & hwp.Method.ToString & vbCrLf &
"获取响应的http版本: " & hwp.ProtocolVersion.ToString & vbCrLf &
"获取响应的原始地址: " & hwp.ResponseUri.ToString & vbCrLf &
"获取响应的服务器名称:" & hwp.Server.ToString & vbCrLf &
"获取是否支持标题的值:" & hwp.SupportsHeaders.ToString
End Sub
End Class
四、参数传递
数据会以两种方式传送至服务器主机,GET及POST。
GET方法会将网页上捜集到的用户字段数据附加到网址后方,传送到网页主机;
另外一种数据传输方式POST, 则将取得的数据写入HTTP文件头,与其他的文件头数据一起传送。
GET方法可从网址列可以看到所传送的数据内容,适合使用没有机密性的数据内容;
POST则适用于敏感性的数据,如账号、密码等。
无论GET或是POST,网页域值均是以如下的形式进行传送:
fieldNamel=valuel & fieldName2=value2 …
其中的fieldNamel为域名,valuel域值,“&”用以连接其他的字段及域值。
当传送的方法为GET时,这一段参数值以符号“?”连接在网址列文字的后方,随着网址列字符串一起送出;若是方法为“POST”,则合并HTTP标头传送出去。
HttpWebRequest 与 HttpWebResponse 类具备传递参数功能。
HttpWebRequest类提供的属性值Method,用以设置传输方式GET或POST;它默认为GET,需POST时将字符”POST”设置给它:
Public Property Method As String
利用GET传输数据
只需将所要传递的参教字符串以“?”符号连接到网址列合并成为一个长字符串,并且将其当做参数,引用WebRequest类 的Create方法,建立WebRequest对象,成为HttpWebRequest对象,接下来的工作便与上前面下载网页内容的过程相同。响应的结果就是为服务器接收参数之后经过处理的结果。
利用POST传输数据
将Method属性设为 POST,收集字段参数值之后,取得HttpWebRequest对象用以写入数据的数据流,将参数字符串写入数据流,设置相关属性之后,才能取得服务器的响应结果,步骤如下:
(1)建立 HttpWebRequest 对象。
(2)设置Method属性等于POST。
(3)设置ContentLength属性值为参数数据的长度,表示所要传送的数据内容长度值。
(4)设置ContentType属性值,指定其所要传送的媒体类型,如下一个参数值在参数传递时被使用:
application/x-www-form-urlencoded
Content-Type,用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件。如果未指定 ContentType,默认为TEXT/HTML。
(5)引用HttpWebRequest类的GetRequestStream方法,取得数据流对象,并且将参 数值传入,GetRequestStream方法取得用来接收应用程序传送数据给HttpWebRequest的数 据流对象,其定义如下,其中的返回值是一个Stream类对象。
Public Function GetRequestStream() As Stream
(6)取得HttpWebResponse对象,将服务器根据参数响应的数据内容取回。
五、举例
找了半天,没找到同时支持Get与Post两种方法的网页,无奈各选一个网址来测试。
1、Get方法使用http://www.silukee.com/小说网上的搜索(因为这里找到了method=”get”),搜索的关键源代码如下:
<form name="ssform" method="get" action="http://www.silukee.com/SearchBook.aspx" onsubmit="if(keyword.value=='' || keyword.value=='请输入小说或作者名称'){alert('请输入小说或作者名称,别输错别字哦:)');return false;}">
<div class="inp">
<span><input name="keyword" type="text" size="22" maxlength="30" value="请输入书名、作者" title="请正确输入" onfocus="this.style.color = '#000000';this.focus();if(this.value=='请输入书名、作者'){this.value='';}" onblur="if(this.value==''){this.value='请输入书名、作者';}" ondblclick="javascript:this.value=''"/></span><span><input class="bn-srh" type="submit" value="搜索" title="搜索"/><input type="hidden" name="t" value="1"/></span>
关键的有http://www.silukee.com/SearchBook.aspx,域值keyword和t,组成的搜索页为:
http://www.silukee.com/SearchBook.aspx?keyword=23&t=12、Post方法使用http://www.999wx.com/user/login.aspx上的登录,这里找到了method=”POST”,登录的关键代码:
<form action="/User/LoginCheck.aspx" method="post" name="LoginFrom">
<div class="loginbox1">
<span>通行证账号:</span>
<input type="text" name="username" id="username" size="22" class="text user" tabindex="1"/>
<div class="spline"></div>
<span>通行证密码:</span>
<input type="password" name="password" id="password" size="22" class="text pass" tabindex="2"/>
<div class="spline"></div>
<label><input type="checkbox" value="30" name="CookieTime" checked/>自动登录</label>
<label class="forget"><a href="/user/ForgetPass.aspx">找回密码</a></label>
<div class="spline"></div>
<input type="submit" class="submit" name="UserLogin" value="登录"/>
<input type="button" class="submit" onclick="window.open('/user/RegtersSave.aspx','','')" name="regedit" value="注册"/>
</div>
</form>
1、get时的情况:
2、POST的情况:
代码如下:
Imports System.Net
Imports System.IO
Imports System.Text
Public Class Form1
Private Sub btnGet_Click(sender As Object, e As EventArgs) Handles btnGet.Click
'Get方式
Dim hwq As HttpWebRequest
Dim hwp As HttpWebResponse
Dim sr As StreamReader
Dim strAddress As String
strAddress = txtGetAddress.Text & "?" & "keyword=66&t=1"
Try
hwq = CType(HttpWebRequest.Create(strAddress), HttpWebRequest)
'hwq.Method = "GET" 默认为Get,所以不用设置
hwp = CType(hwq.GetResponse, HttpWebResponse)
sr = New StreamReader(hwp.GetResponseStream)
txtContent.Text = sr.ReadToEnd
sr.Close()
Catch ex As Exception
txtContent.Text = ex.Message
End Try
End Sub
Private Sub btnPost_Click(sender As Object, e As EventArgs) Handles btnPost.Click
'Post方式
Dim hwq As HttpWebRequest
Dim hwp As HttpWebResponse
Dim st As Stream
Dim sr As StreamReader '从响应流中得到数据
Dim strPostInfo As String
Dim a() As Byte
strPostInfo = "username=getpost&password=get123456"
a = Encoding.ASCII.GetBytes(strPostInfo) '转为字节流,以便注入请求流中(请求流不能出现=)
Try
hwq = CType(HttpWebRequest.Create(txtPostAddress.Text), HttpWebRequest)
'post信息
hwq.Method = "POST"
hwq.ContentLength = a.Length
hwq.ContentType = "application/x-www-form-urlencoded"
hwq.Referer = "http://www.999wx.com/user/login.aspx" '请求前网址,此句不能省
st = hwq.GetRequestStream
st.Write(a, 0, a.Length) '注入post信息
hwp = CType(hwq.GetResponse, HttpWebResponse)
sr = New StreamReader(hwp.GetResponseStream, Encoding.Default)
txtContent.Text = sr.ReadToEnd
sr.Close()
Catch ex As Exception
txtContent.Text = ex.Message
End Try
End Sub
End Class