1 / 31

C# 网络编程技术教程

C# 网络编程技术教程. 第九章 HTTP 编程. 学习目标. 了解 HTTP 、 HTTP 标题、 HTTP 方法、 HTTP 响应、 URL 等。 掌握 HTTP 信息交换过程。 掌握 .NET 环境下基于 Socket 类的 HTTP 编程方法。 掌握 .NET 环境下基于 TcpListener 类的 HTTP 编程方法。. 本章内容. 9.1 HTTP 概述 9.2 .NET 中 HTTP 编程 9.3 基于 HTTP 的编程实例. 9.1 HTTP 概述.

jackie
Download Presentation

C# 网络编程技术教程

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. C#网络编程技术教程 第九章 HTTP编程

  2. 学习目标 • 了解HTTP、HTTP标题、HTTP方法、HTTP响应、URL等。 • 掌握HTTP信息交换过程。 • 掌握.NET环境下基于Socket类的HTTP编程方法。 • 掌握.NET环境下基于TcpListener类的HTTP编程方法。

  3. 本章内容 9.1 HTTP概述 9.2 .NET中HTTP编程 9.3 基于HTTP的编程实例

  4. 9.1 HTTP概述 HTTP(Hypertext Transfer Protocol,超文本传输协议)是用于从WWW服务器传输超文本到本地浏览器的传送协议。它可以使浏览器更加高效,使网络传输量减少。它不但能保证计算机正确快速地传输超文本文档,还能确定传输文档中的哪一部分,以及哪部分内容首先显示(如文本先于图形)等。 HTTP是基于请求/响应模式(客户机/服务器)的协议。一个客户机与服务器建立连接后,发送一个请求给服务器,请求方式的格式为:统一资源定位符(URL)、协议版本号,后边是MIME信息(包括请求修饰符、客户机信息和可能的内容)。服务器接到请求后,给予相应的响应信息,其格式为一个状态行,包括信息的协议版本号、一个响应成功或失败的代码,后边是MIME信息(包括服务器信息、实体信息和可能的内容)。 HTTP目前的版本有1.0和1.1两种,分别由以下的RFC所制定: RFC 1945 Hypertext Transfer Protocol—HTTP/1.0  RFC 2068 Hypertext Transfer Protocol—HTTP/1.1  RFC 2016 Hypertext Transfer Protocol—HTTP/1.1 其中定义了以下重要的协议: HTTP标题 HTTP方法 HTTP响应信息 URL  HTTP流程

  5. 9.1 HTTP概述 9.1.1 HTTP标题 当客户端通过浏览器向服务器端发送请求时,HTTP将请求转化为协议可以识别的HTTP标题信息传送至Web服务器处理。例如: GET http://download.microtool.de:80/index.html HTTP/1.1 Accept:image/gif,image/jpeg,image/pjpeg,*/* Referer:http://download.microtool.de/ Accept-Language:zh-cn User-Agent:Mozilla/4.0 (Windows NT 5.0;MSIE 5.01) Host”download.microtool.de 此HTTP标题包含了以下重要的信息: 1.GET 代表客户端向服务器端发送HTTP请求的方法,可以分为以下几种。 GET(通过请求URI得到资源)。 POST(用于添加新的内容)。 HEAD(类似于GET,但是不返回body信息,用于检查对象是否存在,以及得到对象的元数据)。 PUT(用于修改某个内容)。 DELETE(删除某个内容)。 CONNECT(用于代理进行传输,例如使用SSL)。 OPTIONS(询问可以执行哪些方法)。 TRACE(用于远程诊断服务器)。

  6. 9.1 HTTP概述 9.1.1 HTTP标题 2.http://download.microtool.de:80/index.html 代表客户端请求的资源,以URI或者URL的形式表示。 3.HTTP/1.1 代表使用HTTP的版本。 一般情况下,通过以上三类HTTP请求信息,服务器便能够了解客户端的HTTP请求是什么,并且能够确定请求资源的位置,并根据上述得到的信息进一步做出相应的响应。 除了上述信息之外,HTTP标题还包含以下信息: (1)Accept表示客户端可以处理的媒体类型,如下列格式。这些媒体的类型可以按照优先级进行排序。若为*/*,则代表客户端可以接受所有类型的媒体形式。 Application/word  Application/excel  Application/pdf  Application/zip  Application/xml  image/jpeg  image/gif  text/css  text/html  video/mpeg

  7. 9.1 HTTP概述 9.1.1 HTTP标题 (2)Accept-Charset:定义客户端可以处理的字符集,按照优先级进行排序。在一个以逗号为分隔的列表中,可以定义多种类型和使用通配符。例如:Accept-Charset: iso-8859-1,*,utf-8。 (3)Accept-Encoding:定义客户端可以理解的编码机制。例如:UTF7、UTF8、Unicode等。 (4)Accept-Language:定义客户端可以接受的自然语言列表。例如:Accept-Language: en,zh-cn。 (5)Connection:用于表明是否保存socket连接作为开放的通用标头。例如:Connection: close或Connection: keep-alive。 (6)Content-Base:用于定义基本URI的实体标头,为了在实体范围内解析相对URLs。 如果没有定义Content-Base标头解析相对URLs,则使用Content-Location URI(存在且绝对)或使用URI请求。例如:Content-Base: Http://www.myweb.com。 (7)Content-Encoding:一种媒体类型修饰符,标明一个实体是如何编码的。例如:Content-Encoding:zip。 (8)Content-Length:指定服务器端响应中数据的字节长度。例如:Content- Length:382。 (9)Content-Range:随实体部分一同发送,标明被插入字节的低位与高位字节偏移,也标明此实体的总长度。例如:Content-Range: 1001-2000/5000。 (10)Content-Type:标明发送或者接收的实体的MIME类型。例如:Content-Type: text/html。 (11)Host:服务器的主机名。对于使用HTTP/1.1的请求而言,此域是强制性的。例如:Host:www.myweb.com。 (12)Referer:表明客户端上一次所浏览的资源,通过Referer的内容,可令浏览器更快速地执行“上一页”的功能。 (13)User-Agent:定义用于产生请求的软件类型(典型的如Web浏览器)。例如:User- Agent:Mozilla/4.0(compatible;MSIE 5.5;Windows NT)。

  8. 9.1 HTTP概述 9.1.2 HTTP方法 当客户端向服务器端发送HTTP请求时,HTTP请求信息会随着HTTP方法一起传输到服务器,以告知服务器如何处理客户端的请求。 HTTP方法根据版本的不同会有所差异。其语法一般为: <HTTP Method><URI>HTTP/<HTTP Version><CRLF> 例如: GET www.cctv.com/default.html http/1.1 (1)GET:HTTP协议的一种基本方法。GET用来取回请求URI标志的任何信息。“GET”这个单词就是“获取”的意思。如果请求URI指向的是一个数据处理过程,那么返回的结果是数据处理过程的结果,而不是数据处理程序的代码。 如果HTTP标题中包含If-Modified-Since、If-Unmodified-Since、If-Match、If-None-Match或If-Range等条件字段,那么GET就变成了一个“有条件的GET”。只有满足条件,数据才会被返回。这样可以减少一些非必要的网络传输,或减少对某一资源的多次请求(一般的浏览器都有一个临时目录,用来缓存一些网页信息,当再次浏览某个页面的时候,只下载那些修改过的内容,以加快浏览速度,就是这个道理。至于检查,则常用比GET更好的方法HEAD来实现)。如果HTTP包中含有Range头字段,那么请求URI指定的实体中,只有决定范围条件的那部分才被取回来。

  9. 9.1 HTTP概述 9.1.2 HTTP方法 (2)HEAD:HTTP的HEAD方法和GET方法一样,唯一的差别就是服务器不能响应包含主体(Message-body)的请求。使用这个方法,可以使客户无需将资源下载就可以得到一些关于它的基本信息。这个方法常用来检查超级链接的可访问性以及资源最近有没有修改。HEAD方法经常用于获取资源的基本信息。 (3)POST:HTTP的POST方法就是要求服务器接受请求标题中的实体(Message-Body),并且将其作为请求URI的下属资源。这意味着首先服务器要保存这个实体信息,而且由服务器程序进行处理。POST方法一般包含两个步骤:为请求标题准备数据,然后读取服务器应答的数据信息。 (4)DELETE:客户端通过DELETE方法删除所定位的资源,但需要注意的是,服务器必须打开写入权限,以便修改目录下的文件,否则,DELETE将执行失败。 (5)PUT:正好与DELETE方法相反,客户端利用PUT方法在服务器上建立所指定的资源(如文件),如果资源已经存在,那么就将原来的资源覆盖。此方法一般用于向服务器上传文件。和DELETE方法一样,服务器必须打开自己的写入权限,否则,PUT方法将执行失败。

  10. 9.1 HTTP概述 9.1.2 HTTP方法 HTTP还有以下一些方法,有兴趣的读者可以参考RFC的说明。 (1)CHECKIN (2)CHECKOUT (3)CONNECT (4)LINK (5)OPTIONS (6)TRACE (7)UNLINK 9.1.3 HTTP响应信息 和其他的协议一样,HTTP协议也有自己的响应信息来表示客户端请求执行的情况。HTTP响应信息由三部分组成,分别是:状态行、消息报头、响应正文。 状态行的格式如下: HTTP-Version Status-Code Reason-Phrase CRLF 其中,HTTP-Version表示服务器HTTP协议的版本;Status-Code表示服务器发回的响应状态代码;Reason-Phrase表示状态代码的文本描述。 状态代码由三位数字组成,如表9.1所示,第一个数字定义了响应的类别,且有5种可能取值,如表9.2所示。

  11. 9.1 HTTP概述 9.1.4 URL URL的全名为Uniform Resource Locator(统一资源定位符),它不仅可用来定位网络上信息资源的地址,也可用来定位本地系统要访问的文件。 URL可以分为两种类型,一种是绝对URL,另一种是相对URL。 绝对URL就是指明需要访问的信息或资源的绝对位置。绝对URL的基本语法格式为:<协议>://<主机名>[:端口]/目录/名。其中,协议指定资源服务器的服务方式。WWW系统中,最常用的是“http”协议。主机名,指服务器域名,接入到因特网中的每个可供访问的服务器,都有一个专用的域名,用户要访问服务器上的资源,必须指明服务器的域名。端口是指明进入一个服务器的端口号,用数字表示,一般可缺省。目录是指文件所在服务器的目录或路径。名字是指文件名,在缺省的情况下,首先会调出称为“主页”的文件。 相对URL就是定位需要访问资源的相对路径。所谓的“相对路径”,就是所需资源相对于当前位置的路径。例如,当我们已处于服务器中的一个路径时,如果该路径中有多个文件需要访问,那么只需要指出文件名就可以了。

  12. 9.1 HTTP概述 9.1.5 HTTP流程 HTTP流程是指基于HTTP的客户机/服务器模式的信息交换过程。HTTP流程一般由四个过程组成,如图9.1所示。分别是建立连接、发送请求信息、发送响应信息和关闭连接。 1.建立连接 连接的建立是通过申请套接字实现的。客户打开一个套接字并把它约束在一个端口上,如果成功,就相当于建立一个虚拟文件。以后就可以在该虚拟文件上写数据并通过网络向外传送。 图9.1 HTTP流程

  13. 9.1 HTTP概述 9.1.5 HTTP流程 2.发送请求 打开一个连接后,客户机把请求消息发送到服务器的相应端口上,完成提出的请求动作。HTTP/1.0请求消息的格式为: 请求消息=请求行 CRLF[实体内容] 请求行=方法 请求URLHTTP版本号 CRLF 方法=GET|POST|HEAD|扩展方法 URL=协议名称+主机名+目录与文件名 一个请求的例子为:GET www.cctv.com/default.html HTTP/1.0 3.发送响应 服务器在处理完客户端的请求之后,要向客户端发送响应消息。 HTTP/1.0的响应消息格式如下: 响应消息=状态行(通用信息头|响应头|实体头)CRLF 状态行=HTTP版本号 状态码 原因叙述 状态码表示响应类型 1××  保留 2××  表示请求成功接收 3××  为完成请求客户需进一步细化请求 4××  客户错误 5××  服务器错误 响应头的信息包括:服务程序名,通知客户请求的URL需要认证,请求的资源何时能使用。 4.关闭连接 客户端和服务器双方都可以通过关闭套接字来结束TCP/IP对话。

  14. 9.2 .NET中HTTP编程 9.2.1 基于Socket类的服务器编程 前面已经介绍了HTTP协议内容的基础,本小节主要介绍如何使用Socket类来设计供多人使用的HTTP Web服务器。 Web服务器和其他服务器的处理过程大致相同,具体步骤如下。 ① 用户使用Web浏览器通过HTTP协议向Web 服务器发送请求指令。例如http://www.cctv.com/default.html。 ② 建立和服务器之间的连接。服务器端通过HTTP信息,可以了解客户端的请求是什么,并进一步处理和返回相应的资源。 ③ 关闭客户端和服务器之间的连接。 具体处理上述过程时,可以细化为以下几个部分。 (1)处理多人连接的情况:在C#中,一般使用多线程来处理多人连接。服务器端收到客户端的请求时,用Socket类的Accept方法建立和客户端连接的Socket对象。 代码示例如下: while(true){ try{ socketClient=socketServer.Accept( ); … //使线程和每一个HTTP客户端连接 Thread ThreadClient=new Thread(new ThreadStart(this.ProcessRequest)); ThreadClient.Start( ); } catch(Exception ex) { Console.WriteLine(ex.Message.ToString( )); } if(socketClient.Connected) socketClient.close( ); }

  15. 9.2 .NET中HTTP编程 9.2.1 基于Socket类的服务器编程 (2)取得Web浏览器的HTTP请求,使用Socket类的Receive方法取得。示例如下: bytes=socketClient.Receive(recvBytes,0,socketClient.Available,SocketFlag.None); htmlReq=Encoding.ASCII.GetString(recvBytes,0,bytes); (3)定义虚拟目录:程序中指定项目所在目录为网址的主目录。 String rootPath=Directory.GetCurrentDirectory( )+"\\wwwRoot\\"; (4)HTTP方法及请求浏览的资源。Web服务器需要从HTTP标题中取得HTTP方法及其资源。程序示例如下: strArray=htmlReq.Trim( ).Split(" ".ToCharArray( )); if(strArray[0].Trim( ).ToUpper( ).Equals("GET")) { strRequest=strArray[1].Trim( ).ToString( ); if(strRequest.StartsWith("/")) strRequest=strRequest.Substring(1); if( strRequest.EndsWith("/")|| strRequest.Equals("")) strRequest= strRequest+defaultPage; strRequest=rootPath+ strRequest; sendHTMLResponse(strRequest); } else { strRequest=rootPath+"Error\\"+"400.html"; endHTMLResponse(strRequest); }

  16. 9.2 .NET中HTTP编程 9.2.1 基于Socket类的服务器编程 取得请求浏览的资源之后,则必须从虚拟目录下寻找对应的文件是否存在,如果存在,则用Socket类的Send方法响应HTML标题及网页内容至客户端Web浏览器。程序示例如下: ① 标题 SocketClient.Send(headerByte,0,heardByte.Length,SocketFlags.None); ② 网页内容 SocketClient.Send(contentByte,0,contentByte.Length,SocketFlags.None); (5)处理MIME。MIME是由资源的扩展名所决定的,通常定义以下的MIME。 if (httpRequest.EndWith("html")) return "text/html"; else if (httpRequest.EndWith("htm")) return "text/htm"; else if (httpRequest.EndWith("txt")) return "text/plain"; else if (httpRequest.EndWith("gif")) return "image/gif"; else if (httpRequest.EndWith("jpg")) return "image/jpeg"; else if (httpRequest.EndWith("pdf")) return "Application/pdf"; else if (httpRequest.EndWith("doc")) return "Application/msword"; else return "text/plain"; 一般的Web服务器均把MIME对应定义在文件中,以便进行修改。 (6)最后,当传输结束时,Web服务器需关闭客户连接。程序示例如下: SocketClient.Shutdown(SocketShutdown.Both); SocketClient.Close( );

  17. 9.2 .NET中HTTP编程 9.2.2 基于TcpListener类的服务器编程 Web服务器编程方法除了使用System.Net.Socket的Socket类之外,也可以使用基于TcpListener类的方法实现。流程如图9.2所示,程序如代码实例9.1所示。 (1)首先Web服务器以TcpListener类建立服务器Socket,对某个端口进行监听(例如,8080),以等待客户端连接到该端口。 (2)处理客户端的连接:建立客户端连接,可以使用TcpListener类的AcceptSocket方法或者AcceptTcp Client方法。AcceptSocket方法可以接受客户端的请求,并且建立与客户端连接的Socket。 (3)处理数据的传送或接收:使用Socket类的Send与Receive方法来传输及接收数据。 (4)完毕时,关闭Web浏览器和Web服务器的Socket连接。 图9.2基于TcpListener类的实现流程

  18. 9.2 .NET中HTTP编程 9.2.2 基于TcpListener类的服务器编程 using System; using System.IO; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading ; namespace cnnbsun.webserver { class MyWebServer { private TcpListener InstanceLst ; private int port = 8080 ; public MyWebServer( ) { try{ InstanceLst = new TcpListener(port) ; InstanceLst.Start( ); Console.WriteLine("Web Server Running... Press ^C to Stop..."); Thread ListTh= new Thread(new ThreadStart(StartListen)); ListTh.Start( ) ; } catch(Exception e) { Console.WriteLine("监听端口时发生错误:" +e.ToString( )); } } public void SendHeader(string sHttpVersion, string sMIMEHeader, int iTotBytes, string sStatusCode, ref Socket mySocket)

  19. 9.2 .NET中HTTP编程 9.2.2 基于TcpListener类的服务器编程 { String sBuffer = ""; if (sMIMEHeader.Length == 0 ) { sMIMEHeader = "text/html"; // 默认text/html } sBuffer = sBuffer + sHttpVersion + sStatusCode + "\r\n"; sBuffer = sBuffer + "Server: cx1193719-b\r\n"; sBuffer = sBuffer + "Content-Type: " + sMIMEHeader + "\r\n"; sBuffer = sBuffer + "Accept-Ranges: bytes\r\n"; sBuffer = sBuffer + "Content-Length: " + iTotBytes + "\r\n\r\n"; Byte[] bSendData = Encoding.ASCII.GetBytes(sBuffer); SendToBrowser( bSendData, ref mySocket); Console.WriteLine("Total Bytes : " + iTotBytes.ToString( )); } public void SendToBrowser(String sData, ref Socket mySocket) { SendToBrowser (Encoding.ASCII.GetBytes(sData), ref mySocket); } public void SendToBrowser(Byte[] bSendData, ref Socket mySocket) { int numBytes = 0; try{ if (mySocket.Connected) { if (( numBytes = mySocket.Send(bSendData, bSendData.Length,0)) == -1) Console.WriteLine("Socket Error cannot Send Packet"); else{ Console.WriteLine("No. of bytes send {0}" , numBytes); } }

  20. 9.2 .NET中HTTP编程 9.2.2 基于TcpListener类的服务器编程 else Console.WriteLine("连接失败...."); } catch (Exception e) { Console.WriteLine("发生错误: {0} ", e ); } } public static void Main( ) { MyWebServer MWS = new MyWebServer( ); } public void StartListen( ) { int iStartPos = 0; String sRequest; String sDirName; String sRequestedFile; String sErrorMessage; String sLocalDir; String sMyWebServerRoot = "E:\\MyWebServerRoot\\"; //设置你的虚拟目录 String sPhysicalFilePath = ""; String sFormattedMessage = ""; String sResponse = ""; {Socket mySocket = InstanceLst.AcceptSocket( ) ; Console.WriteLine ("Socket Type " +mySocket.SocketType ); if(mySocket.Connected) { Console.WriteLine("\nClient Connected!!\n==================\nCLient IP {0}\n",mySocket.RemoteEndPoint) ;

  21. 9.2 .NET中HTTP编程 9.2.2 基于TcpListener类的服务器编程 Byte[] bReceive = new Byte[1024] ; int i = mySocket.Receive(bReceive,bReceive.Length,0) ; string sBuffer = Encoding.ASCII.GetString(bReceive); if (sBuffer.Substring(0,3) != "GET" ) { Console.WriteLine("只处理get请求类型.."); mySocket.Close( ); return; } iStartPos = sBuffer.IndexOf("HTTP",1); string sHttpVersion = sBuffer.Substring(iStartPos,8); sRequest = sBuffer.Substring(0,iStartPos - 1); sRequest.Replace("\\","/"); if ((sRequest.IndexOf(".") <1) && (!sRequest.EndsWith("/"))) { sRequest = sRequest + "/"; } iStartPos = sRequest.LastIndexOf("/") + 1; sRequestedFile = sRequest.Substring(iStartPos); sDirName = sRequest.Substring(sRequest.IndexOf("/"), sRequest.LastIndexOf("/")-3); sLocalDir = sMyWebServerRoot; Console.WriteLine("请求文件目录: " + sLocalDir); if (sLocalDir.Length == 0 ) { sErrorMessage = "<H2>Error!! Requested Directory does not exists</H2><Br>"; SendHeader(sHttpVersion, "", sErrorMessage.Length, " 404 Not Found", ref mySocket); SendToBrowser(sErrorMessage, ref mySocket); mySocket.Close( ); continue; }

  22. 9.2 .NET中HTTP编程 9.2.2 基于TcpListener类的服务器编程 Byte[] bReceive = new Byte[1024] ; int i = mySocket.Receive(bReceive,bReceive.Length,0) ; string sBuffer = Encoding.ASCII.GetString(bReceive); if (sBuffer.Substring(0,3) != "GET" ) { Console.WriteLine("只处理get请求类型.."); mySocket.Close( ); return; } iStartPos = sBuffer.IndexOf("HTTP",1); string sHttpVersion = sBuffer.Substring(iStartPos,8); sRequest = sBuffer.Substring(0,iStartPos - 1); sRequest.Replace("\\","/"); if ((sRequest.IndexOf(".") <1) && (!sRequest.EndsWith("/"))) { sRequest = sRequest + "/"; } iStartPos = sRequest.LastIndexOf("/") + 1; sRequestedFile = sRequest.Substring(iStartPos); sDirName = sRequest.Substring(sRequest.IndexOf("/"), sRequest.LastIndexOf("/")-3); sLocalDir = sMyWebServerRoot; Console.WriteLine("请求文件目录: " + sLocalDir); if (sLocalDir.Length == 0 ) { sErrorMessage = "<H2>Error!! Requested Directory does not exists</H2><Br>"; SendHeader(sHttpVersion, "", sErrorMessage.Length, " 404 Not Found", ref mySocket); SendToBrowser(sErrorMessage, ref mySocket); mySocket.Close( ); continue; }

  23. 9.2 .NET中HTTP编程 9.2.2 基于TcpListener类的服务器编程 if (sRequestedFile.Length == 0 ) {sRequestedFile = "index.html";} String sMimeType = "text/html"; sPhysicalFilePath = sLocalDir + sRequestedFile; Console.WriteLine("请求文件: " + sPhysicalFilePath); if (File.Exists(sPhysicalFilePath) == false) {sErrorMessage = "<H2>404 Error! File Does Not Exists...</H2>"; SendHeader(sHttpVersion, "", sErrorMessage.Length, " 404 Not Found", ref mySocket); SendToBrowser( sErrorMessage, ref mySocket); Console.WriteLine(sFormattedMessage); } else{ int iTotBytes=0; sResponse =""; FileStream fs = new FileStream(sPhysicalFilePath, FileMode.Open, FileAccess.Read, FileShare.Read); BinaryReader reader = new BinaryReader(fs); byte[] bytes = new byte[fs.Length]; int read; while((read = reader.Read(bytes, 0, bytes.Length)) != 0) {sResponse = sResponse + Encoding.ASCII.GetString(bytes,0,read); iTotBytes = iTotBytes + read;} reader.Close( ); fs.Close( ); SendHeader(sHttpVersion, sMimeType, iTotBytes, " 200 OK", ref mySocket); SendToBrowser(bytes, ref mySocket);} mySocket.Close( );}} } } }

  24. 9.2 .NET中HTTP编程 9.2.3 获取网页内容 本小节主要介绍根据给定的URI来获取对应网页的内容,此功能类似于IE浏览器中的“查看源文件”。主要是使用HttpWebRequest类、WebRequest类和远程Web主机创建Http连接,然后通过WebResponse和Http WebResponse获得从Web主机返回的数据流,这些数据流就是Web主机对应的Web页面的内容。除此之外,也可以使用System.Net.Socket的Socket类通过Http协议来获取网页的内容。程序示例如下: IPAddress IPServer=Dns.Resolve(txtURL.Text).AddressList[0]; String Port="80"; IPEndPoint HostServer=new IPEndPoint(IPServer,Int32.Parse(Port)); Socket ClientSocket=new Socket (AddressFamily.InterNetwork,SocketType.Stream ,ProtocolType.Tcp); try{ ClientSocket.Connect(HostServer); if (!ClientSocket.Connected) { MessageBox.Show("连接服务器失败!","提示"); return; } String RequestHttp="GET /HTTP/1.0"+"\r\n"+"\r\n"; ClientSocket.Send(Encoding.ASCII.GetBytes(RequestHttp)); byte[] buffer=new byte[1024]; nt Count=ClientSocket.Receive(buffer,buffer.Length,0); txtHTML.Text=Encoding.ASCII.GetString(buffer,0,Count);

  25. 9.2 .NET中HTTP编程 9.2.3 获取网页内容 while(Count>0) { Count=ClientSocket.Receive(buffer,buffer.Length,0); txtHTML.Text=txtHTML.Text+Encoding.ASCII.GetString(buffer,0,Count); } } catch(Exception ex) { MessageBox.Show(ex.StackTrace.ToString( )); } 说明:在地址文本框中输入域名或者IP地址,例如:www.163.com,首先Socket类利用它的Send方法将请求发送到服务器上,待Web服务器处理之后,则将HTML标题和网页的内容返回至客户端,使用Socket类的Receive方法接收。

  26. 9.3 基于HTTP的编程实例 本节介绍开发一个Internet网页浏览器的实例,使其具有浏览网页、保存网页、打开网页、前进和后退等功能。 9.3.1 界面设计 (1)如图9.3所示,向窗体上拖放1个MainMenu控件、1个ToolBar控件、1个Button控件、1个Label控件、1个TextBox控件和1个AxWebBrowser控件。 (2)菜单的设计,主菜单为文件、查看和帮助。文件菜单下有保存和退出子菜单。查看菜单下有前进、后退、刷新、停止子菜单。 图9.3基于HTTP的编程示例

  27. 9.3 基于HTTP的编程实例 9.3.2 程序设计 1.添加引用 Using System.IO; 2.菜单栏单击事件代码 (1)“保存”菜单项的Click事件代码。 private void pageSave_Click(object sender, System.EventArgs e) { StreamWriter sw=null; SaveFileDialog saveDialog =new SaveFileDialog( ); saveDialog.Filter="网页文件(*.html)|*.html"; if (saveDialog.ShowDialog( )==DialogResult.OK) { try { sw=new StreamWriter(saveDialog.FileName,false,System.Text.Encoding.Unicode ); sw.Write(this.pageWeb.Document ); } catch(Exception ex) { MessageBox.Show(ex.Message.ToString( )); } finally { sw.Close( ); } } }

  28. 9.3 基于HTTP的编程实例 9.3.2 程序设计 (2)“退出”菜单项的Click事件代码。 private void pageExit_Click(object sender, System.EventArgs e) { Application.Exit( ); } (3)“前进”菜单项的Click事件代码。 private void pageUp_Click(object sender, System.EventArgs e) { this.pageWeb.GoForward( ); } (4)“后退”菜单项的Click事件代码。 private void pageDown_Click(object sender, System.EventArgs e) { this.pageWeb.GoBack( ); } (5)“刷新”菜单项的Click事件代码。 private void pageRefresh_Click(object sender, System.EventArgs e) { this.pageWeb.Refresh( ); } (6)“停止”菜单项的Click事件代码。 private void pageStop_Click(object sender, System.EventArgs e) { this.pageWeb.Stop( ); }

  29. 9.3 基于HTTP的编程实例 9.3.2 程序设计 3.工具栏单击事件 Private void toolBar1_ButtonClick(object sender, System.Windows.Forms.ToolBarButton ClickEventArgs e) { switch(toolBar1.Buttons.IndexOf(e.Button )) { case 0: pageSave.PerformClick( ); break; case 1: pageUp.PerformClick ( ); break; case 2: pageDown.PerformClick( ); break; case 3: pageRefresh.PerformClick( ); break; case 4: pageStop.PerformClick( ); break; case 5: pageExit.PerformClick( ); break; } }

  30. 9.3 基于HTTP的编程实例 9.3.2 程序设计 4.浏览网页和向地址栏添加地址的过程 private void Navigate( ) { object aObject=new object( ); try { this.pageWeb.Navigate(this.cmbAddress.Text,ref aObject,ref aObject,ref aObject,ref aObject); } catch(Exception ex) { Console.Write(ex.StackTrace.ToString( )); } AddAddress( ); } private void AddAddress( ) { int AddressIndex=this.cmbAddress.FindStringExact(this.cmbAddress.Text); if(AddressIndex<0) { this.cmbAddress.Items.Add(this.cmbAddress.Text); } }

  31. 9.3 基于HTTP的编程实例 9.3.2 程序设计 5.“进入”按钮的Click事件代码 private void btnEnter_Click(object sender, System.EventArgs e) { Navigate( ); } 6.地址栏按键事件的代码 private void cmbAddress_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e) { if (e.KeyChar ==(char)13) { Navigate( ); } }

More Related