第16章Intranet与Internet编程_第1页
第16章Intranet与Internet编程_第2页
第16章Intranet与Internet编程_第3页
第16章Intranet与Internet编程_第4页
第16章Intranet与Internet编程_第5页
已阅读5页,还剩12页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第16章 Intranet与Internet编程最早出现的网络协议分为两个集合,二者一同出现,分别是TCP和IP。TCP(传输控制协议)和IP(网际协议)通过协作,在局域网、内部网、外部网和Internet连接之上提供了一个逻辑层。局域网是计算机通过导线和网卡(NIC卡)在物理上连接起来,或像我家里和办公室那样,通过无线连接。楼下供孩子用的计算机使用AirEzy 2405无线收发器,使得地下室中的计算机可以连接到我办公室的局域网,进而又连接到Internet。这样孩子们可以上网冲浪、玩Half Life游戏;而其他工作也可以同时进行。TCP协议并未涉及过多细节,其中包括了对报文头的描述,可以使

2、数据在网络上漫游。TCP协议会维护状态信息,使得连接的两端可以相互了解。IP协议向报文添加了特定的头部信息,用于对点分IP地址进行分类和解析。例如,77与域名相关联。我的ISP服务提供商向DNS(域名服务器)添加了一个名字项,将与关联起来。当向我的网站收发信息时,IP数据报中包括了寻址信息。在数据包由工作站移动到集线器再移动到网络服务器,通过铜缆调制解调器(经AT&T许可),再经过路由器和其他服务器的过程中,TCP和IP协议定义了跟踪数据的手段。其他协议如Gopher等在TCP/IP出现之前很流行,在TCP/IP层之上还有其他基于TCP/IP的协议,这些协议都

3、是具有特定用途的。例如,FTP(File Transfer Protocol,文件传输协议)用于方便网络上的文件传输。UDP(User Datagram Packet,用户数据报)协议是无连接的,它由TCP/IP发展而来,并不维护客户与服务器之间的连接信息,它在某些方面非常有用,如流类型的媒体,其中有一些报文丢失是可以接受的。如果想要深入了解各种协议的细节,包括TCP/IP、FTP、UDP、Gopher等等,可能需要找一本书来看看,如Que出版的Using TCP/IP,作者是John Ray。另一种方法是,可以查找特定的RFC(Request For Comment)和白皮书,来阅读有关特定

4、协议的所有细节。本章并不讲述有关协议的底层细节,但您可以学到如何使用Delphi提供的各种组件和类,对大多数常见的协议进行编程。Delphi 6中新增了来自Nevrona的Internet Direct组件。除了前一版本的Delphi提供的Internet和Fastnet组件之外,在Internet Direct或Indy中包括了许多客户和服务器端的组件来支持TCP/IP、UDP、Echo、Finger、Gopher、HTTP、POP3、SMTP,NNTP和Telnet等协议。对特定协议内容的简要评论可能较为有用,除此之外,本章还将示范许多新的客户和服务器端组件。到本章结束,通过使用这些强大的

5、组件,您可以学到大量Internet和内部网编程技术,还可以在实例程序中很好的实践一下。16.1 传输控制协议(TCP)组件组件面板Indy Clients和Indy Servers属性页上的IdTCPClient和IdTCPServer组件直接支持TCP协议,而Internet属性页上来自Borland公司的TcpClient和TcpServer组件也同样支持该协议。由于支持TCP的Indy组件较新,本节我们将把注意力集中于它们。请记住,两对组件都支持同一协议,而每对组件都可以用TCP编程;而Nevrona和Borland的组件可能在特定的名字和特性上不同。注意:所有的Internet Di

6、rect(Indy)组件都以Id为前缀。16.1.1 Indy客户端TCP组件通过给出服务器的主机名或IP地址,以及服务器程序所监听的端口号,一个TCP客户程序即可连接到TCP服务器。对于Internet或HTTP来说,服务器程序的通用端口号是80。其他已分配的通用端口号包括:FTP协议20和21,Telnet协议23,SMTP协议25,Gopher协议70,POP3协议110。在命令行运行netstat.exe,即可确定系统使用的所有端口号。下面的列表包括了在我的工作站上使用的一部分端口。注意:在巴隆计算机术语词典中,将端口定义为CPU与另一设备(非内存)之间的连接,信息可以通过该连接出入计

7、算机。虽然该定义没有达到非常令人不满的程度,但端口确实是一个被滥用的术语。将一根5型电缆插入到网络接口卡中,插口也可称为端口。对我们的目的而言,端口是微处理器与物理设备之间的一个微小的物理连接。端口号告诉CPU向何处发送数据。扬声器的端口号是$61。在向端口$61发送比特值0和1之后,扬声器将发出稳定的蜂鸣声。而发送另一个值清除01比特,就关掉扬声器。下面的步骤示范了直接向扬声器端口发送数据的过程。1.打开命令行窗口。2.在命令行进入Debug,运行Debug程序。3.Debug程序使用短划线(-)作为命令提示符。在Debug命令提示符后键入o61,3,并敲回车键。4.然后可以听到扬声器发出蜂

8、鸣声。键入o61,0将关掉扬声器。这些指令将直接从微处理器发送到61端口。Active ConnectionsProto Local Address Foreign Address StateTCP ptk800:1025SCI.TCIMET.NET:nbsession ESTABLISHEDTCP ptk800:1482:8888 ESTABLISHEDTCP ptk800:1621SCI.TCIMET.NET:1046 ESTABLISHEDTCP ptk800:1625 SCI.TCIMET.NET:1072 ESTABLISHEDTCP ptk800:1630 SCI.TCIMET.N

9、ET:1046 ESTABLISHEDTCP ptk800:1634 SCI.TCIMET.NET:1072 ESTABLISHEDTCP ptk800:1636 SCI.TCIMET.NET:nbsession ESTABLISHEDTCP ptk800:1026 LocalHost:1029 ESTABLISHEDTCP ptk800:1029 LocalHost:1026 ESTABLISHED即使没有Web服务器来测试应用程序也不要担心;可以使用LocalHost地址来测试客户和服务器程序。另外,也可以建立测试专用的Web服务器,在Windows NT下可以从Network Apple

10、t(控制面板中的网络设置)中安装Peer Web Server,而Windows 98中可以安装Personal Web Server。要在使用Windows NT的计算机上安装Peer Web Server,打开控制面板上的Network Applet。然后转到Services属性页,单击Add按钮。安装过程可能需要Windows NT光盘以完成安装。netstat输出的第二栏中是本地计算机名,后接端口号;第三个栏目是远程计算机,或接收主机和端口号,后接状态。当Foreign Address栏中显示LocalHost时,指的是IP地址,即所谓的loopback地址,PC机可

11、以使用该地址引用其自身。LocalHost的URL是IP地址。注意:由于某些原因,使得运行Peer Web Server是个好主意。首先,规模较小的Web服务器可以成为很好的单元测试平台;其次,它可以迅速而简易地建立起内部网的网站,用于在公司内与您的项目有关的人共享信息。它对于团队开发是既有价值又较为廉价的工具。IdTCPClientInternet Direct TCP客户组件,位于组件面板的Indy Clients属性页上;要测试该组件,需要完成下列步骤并添加列出的代码。1Windows NT下,在控制面板的Network Applet中添加Peer Web Server

12、(Windows 9x下使用Personal Web Server)。默认情况下,该服务器将使用LocalHost地址的80端口以及default.htm页面。2启动Delphi,向默认的空白窗体添加TIdTCPClient组件。3向窗体添加TMemo组件,可在其中放置TCP连接的输出。4向FormCreate事件处理程序添加下列代码。procedure TForm1.FormCreate( Sender : TObject );beginIdTCPClient1.Host := ''IdTCPClient1.Port := 80;IdTCPClient1.C

13、onnect;tryIdTCPClient1.SendCmd('GET /default.htm' );Memo1.Lines.Add( IdTCPClient1.CurrentReadBuffer );finallyIdTCPClient1.Disconnect;end;end;警告:如果为TIdTCPClient.OnStatus编写事件处理程序,需要手工向uses组件添加IdStatus,在该单元中包括了TIdTCPClient.OnStatus事件方法,否则将出现编译错误(当您阅读到这里时,该问题可能已经解决)。代码的第一行将主机的IP地址定义为字符串。可以使用TIPA

14、ddress组件,它可以方便地从用户输入得到IP地址。第二行包含了端口号。对于HTTP协议,通常是80端口,但如果要通过代理服务器,可能是别的端口号,像8080。第三行使用指定的端口号连接到服务器。SendCmd方法向进行响应的服务器发送合适的字符串。GET和POST对于HTTP服务器来说是合适的。命令字符串是否合适是依赖于协议的,例如对于21端口上的FTP协议,其他的命令如LIST可能较为合适。如果要建立支持某个特定协议的程序,可能需要子类化客户和服务器组件,以通过非基于文本的命令集。如果在运行这个简单的示例时出现问题,可以打开Windows NT任务管理器并确认inetinfo.exe已经

15、出现在进程列表中。如果inetinfo.exe(即Peer Web Services)已经运行,可以打开Internet Service Manager(从开始菜单中选择Start | Program Files | Micorsoft Peer Web Services | Internet Service Manager即可)。然后确认TCP端口和Home目录(见图16.1)。在安装Peer Web Services后Web、FTP和Gopher程序被注册为服务程序。在系统启动时,这些程序自动启动。可以使用Internet Service Manager或Services Applet(如

16、图16.2所示)来停止这些服务。也可以使用Services Applet使这些服务在启动时自动运行;如果您在使用内部网,您可能希望这样设置。图16.1 Web Services Properties对话框可以配置Peer Web Server,或确认端口和目录信息图16.2 Peer Web Services在Windows NT中作为服务运行,默认情况下,在Windows启动时,该服务将自动启动在本书的CD-ROM中包括了TCPClient程序的一个稍加完善的版本,TCPClient.dpr。TCPClient程序并不限于使用HTTP服务器。许多通用的协议是基于TCP的,这意味着您可以使用同

17、一TCPClient程序连接到特定类型的服务器。对前面的代码稍加修改,即可连接到FTP服务。IdTCPClient1.Host := ''IdTCPClient1.Port := 21;IdTCPClient1.Connect;tryIdTCPClient1.SendCmd('USER anonymous');IdTCPClient1.SendCmd('PASS me');IdTCPClient1.SendCmd('HELP' );Memo1.Lines.Add( IdTCPClient1.CurrentRead

18、Buffer );finallyIdTCPClient1.Disconnect;end;提示:关于TCP协议的更多知识,可以阅读RFC 0793,位于http:/sunsite. iisc.ernet.in/collection/rfc/rfc0793.html。列出的代码假定您已经安装了FTP服务和Peer Web Services,并在默认情况下允许匿名登录(您也可以在Microsoft Internet Service Manager中确认FTP服务的设置)。通常,您可能觉得特定协议的客户和服务器组件比一般的TCP组件更容易使用。16.1.2 Indy服务器TCP组件IdTCPServe

19、r组件可用于创建TCP服务器程序。TCP服务器组件绑定到一个服务器端口,例如8080,通过响应OnExecute事件在该端口上接收TCP客户请求。例如,如果TCP客户程序使用WriteLn向服务器发送文本,然后即可用OnExecute方法的AThread参数读出客户发送的文本(TIdUDPServer组件的使用可以参见下一节,特性和方法都非常相似)。表16.1列出了TIdTCPServer组件值得注意的特性。表16.1 TIdTCPServer组件的特性。设置Bindings特性(IP:Port)、DefaultPort和Active状态,即可通过传递给OnExecute方法的TIdPeerT

20、hread对象接收客户请求特性描述AcceptWait对客户连接的超时等待时间Active布尔值,表示服务器是否处于激活状态BindingsIP:Port格式的地址字符串,表示服务器所监听的IP地址和端口号DefautlPort监听客户连接的默认端口号Intercept对TIdServerInterceptOpenSSL组件的引用,该组件接收发送到TIdTCPServer组件的数据ThreadMgr对线程管理器集合的引用,其中包括了引用客户连接的线程对象的列表如果要在端口9090创建一个响应客户的服务器程序,需要将DefaultPort特性设置为9090,并把Active特性设置为True。设

21、置好特性后,使用OnExecute事件处理程序和TIdPeerThread参数即可与客户程序进行通信。例如,读出客户程序发送的文本字符串,可使用下列代码:procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);beginShowMessage( AThread.Connection.ReadLnWait );end;TCP服务器组件的事件处理程序IdTCPServer1.OnExecute是通过TIdPeerThread对象的一个实例来调用的。AThread参数中包括了对进行调用TIdTCPServerConnection实例的

22、引用,TIdTCPServerConnection由TIdTCPConnection子类化而来。TIdTCPConnection中包含了发送和接收文本格式数据、字符串命令或TStream对象的方法,还可以检测TCP组件的连接状态。16.2 用户数据报(UDP)组件UDP协议由TCP协议衍生而来。TCP用于确保点对点的连接,而UDP并不保证发送的数据一定到达,也不表明数据报的传输成功或失败。UDP协议所失去的在其速度中得到了补偿。可以发送流化数据的程序中找到UDP的应用,如视频、声音和视频游戏等。对于这种类型的数据,丢失一两帧不会有什么影响,速度才是最重要的。“当程序的目的在于要传输尽可能多的信

23、息时,当数据的丢失相对不重要时,可以使用UDP。(Ray,1999)”注意:当编写本章时,UDP组件只支持发送接收字符串数据,这使得建立能够流化视频和图像的UDP客户和服务器较为困难。也许还会有些变化,等到您使用Delphi 6时,可能已经可以传输TStream对象和二进制数据了。UDP在RFC 0768中描述,可以在/htbin/rfc/rfc0768.html得到。Delphi提供了UDP协议的客户和服务器组件:TIdUDPClient和TIdUDPServer。TIdUDPClientServer.bpg文件中包含了一个客户服务器程

24、序的例子。客户通过发送程序员定义的字符串命令来停止和开始由TMediaPlayer播放的.AVI视频。注意:演示用的客户和服务器程序并不代表着UDP协议的最佳用途,只是对Internet Direct实现的该组件的功能性的示范。为创建使用TIdUDPClient和TIdUDPServer的示例程序,首先创建Delphi工程。然后向工程组再添加一个工程。把一个工程作为客户,另一个作为服务器。为连接到UDP服务器,需要一个TIdUDPClient组件。用来表示服务器的IP地址和端口号。对于示例程序,可以选择一个未被其他基于TCP的协议占用的端口号,如8090。由于UDP是无连接的,因此在UDP的接

25、口方法中不包括Connect方法。要使用Internet Direct实现的组件,只需使用Send向给定的IP地址和端口号广播一个命令字符串。示例中的客户程序向服务器发送“PLAY”和“STOP”字符串。假定一个通常的窗体,使用按钮在播放和停止状态之间进行切换,可以如下实现。procedure TForm1.Button2Click(Sender: TObject);constCommand : string = 'PLAY'beginIdUDPClient1.Send(Command);Memo1.Lines.Add( IdUDPClient1.ReceiveString )

26、;if( Command = 'PLAY' ) thenCommand := 'STOP'elseCommand := 'PLAY'end;较为重要的代码是IdUDPClient1.Send(Command),这个语句很简单。可以注意到其中并未表示连接或断开。服务器是作为应用程序实现的,它对客户程序发出的一个简单的命令集进行响应。为实现服务器,程序将监听DefaultPort端口(8090,与客户相匹配)上的广播,并将TIdUDPServer.Active设置为True。当UDP服务器从客户接收数据时,将调用TIdUDPServer.OnUDPR

27、ead事件处理程序。下面列出的代码示范了如何从OnUDPRead事件的参数中读出数据。procedure TForm2.IdUDPServer1UDPRead(Sender: TObject; AData:TStream;const APeerIP: String; const APeerPort: Integer);varS : TStringStream;beginS := TStringStream.Create('');tryS.CopyFrom( AData, AData.Size );if( CompareText( S.DataString, 'PLAY&

28、#39; ) = 0 ) thenMediaPlayer1.Playelse if (CompareText( S.DataString, 'STOP' ) = 0 ) thenMediaPlayer1.Stop;IdUDPServer1.Send( APeerIP, APeerPort, S.DataString );finallyS.Free;end;end;OnUDPRead有四个参数,类型分别是:TObject、TStream、string和integer。TObject参数表示发送者对象。TStream参数包含了从客户端发送的数据。字符串参数APeerIP,即第三个参

29、数,包含了发送数据的客户计算机的IP地址。APeerPort参数用于标识广播的端口号。提示:本章进行写作时,Delphi 6 beta版并未集成Indy帮助文档和示例程序。当Delphi 6正式版出售时,应该已经包括文档和示例;现在可以访问上面列出的代码使用TStringStream来把数据从TStream对象复制到StringStream,使得代码可以像处理字符串一样处理该数据(另外,也可以使用As操作符来确定TStream对象实际数据类型)。在本例中,把字符串数据与简单的命令集进行比较,然后在使用调用客户的IP地址和端口号将该命令回送到客户端。16.3 建立FTP客户程序文件传输协议(FT

30、P)是一个基于TCP/IP的协议,用于在网络上传输文件。当从Internet下载文件时,可能使用HTTP命令GET,也可能使用FTP。FTP协议具有自身的命令集合,Delphi中包含了一些组件,可用于建立FTP客户程序(例如Ipswitch公司的WS_FTPPro程序和Windows自带的命令行FTP程序)和FTP服务器程序(例如与Microsoft Internet Information Server一同发布的FTP服务器)。注意:在浏览器中,像AOL的Netscape Navigator或Microsoft的Internet Explorer,可能最常用的协议是超文本传输协议(HTTP)

31、,但也可以使用其他几种协议,包括FTP、file、gopher和Telnet。本书的光盘包含了几个FTP示例程序,包括SimpleFTP,它是一个简单的示例程序,使用NetMasters公司的TNMFTP组件实现,该组件可以在组件面板的FastNet属性页上找到,该程序的另一个版本是使用Nevrona公司的TIdFTP组件实现的。除此之外,光盘上还有一个精致的FTP程序FTPPro(如图16.3所示)。FTPPro程序完整的代码并未在此列出,该程序共有大约2000行代码。FTPPro.exe程序还演示了应用程序在注册表中的设置(参考本章稍后POP3示例的章节,其中有一个例子,使用TIniFil

32、e类来把程序设置保存在INI文件中)。FTPPro.exe示例程序还包括了闪烁屏幕、新的shell控件、可选窗体、密码对话框和很多的FTP功能。可以从光盘上复制该程序,并仔细查看一下。本节涵盖了FTP功能中最重要的部分,同时也突出强调了与FTP协议明确相关的代码。图16.3 FTPPro.exe演示了一个基于Windows的FTP客户程序的完整实现,其中使用了NetMasters公司的TNMFTP组件16.3.1 连接到FTP服务器FTP客户程序的所有完整实现都必须满足FTP协议的要求。无论特定的特性和方法是否命名相同,这一点都是必须的。在Delphi中有两个组件可用于创建FTP客户程序。分别

33、是NetMasters LLC公司的TNMFTP组件和Nevrona公司的TIdFTP组件。本节演示了为把FTP客户程序连接到FTP服务器,所有必要的特性和代码实例。使用TNMFTP组件连接到FTP服务器FTP协议要求主机IP和端口号。主机IP可以是如何运行FTP服务器的主机地址,而端口号通常是21。依赖于FTP服务器的配置,您可能需要提供用户名和密码。如果服务器允许匿名登录,那么可以使用anonymous作为用户名,并使用任何包含字符的字符串作为密码(在匿名登录时,通常要求使用电子邮件地址作为密码)。下面的代码演示了匿名登录到FTP站点的过程,其中使用名为NMFTP1的TNMFTP组件。NM

34、FTP1.Host := '77'NMFTP1.Port := 21;NMFTP1.UserID := 'anonymous'NMFTP1.Password := 'yourmail'NMFTP1.Connect;假定主机和端口号是正确的(本例中是正确的),而且服务器允许匿名登录,则上述代码将把FTP客户程序连接到所指定的主机。两种组件都提供了基本的FTP服务,其不同点在于完全性和示范易于实现。在与文件上传和下载相关的章节中提供了一个例子,演示了如何用TNMFTP组件执行基本的FTP服务。FTPPro示例程序是用TNMF

35、TP实现的;您可以从本书的CD-ROM中装载并运行FTPPro工程。认证如果使用TNMFTP组件登录到需要有效用户和密码的站点(而不是匿名登录时),则TNMFTP组件需要进行认证。通过实现TNMFTP.OnAuthenticationNeeded事件处理程序,可以提供动态认证功能。OnAuthenticationNeeded事件处理程序传递一个布尔变量参数Handled。将Handled赋值为True,TNMFTP将继续尝试登录。下面列出的代码示范了认证事件的实现。procedure TFormMain.NMFTP1AuthenticationNeeded(var Handled: Boole

36、an);varUserID, Password : string;beginUserID := NMFTP1.UserID;Password := NMFTP1.Password;Handled := GetPassword( UserID, Password );if( Handled ) thenbeginNMFTP1.Password := Password;NMFTP1.UserID := UserID;end;end;GetPassword是一个全局函数(定义在本书光盘的UFormPassword单元中),该函数创建一个模式对话框窗体,该窗体非常简单,只包括两个输入域,分别代表用户名

37、和密码。代理服务器有些FTP服务器可能会使用代理服务器作为防火墙,以避免黑客攻击;也可能像Software Conceptions公司一样,使用代理服务器向几台工作站通过Internet访问功能。通过设置TNMFTP.Proxy特性,可以指定代理服务器IP地址;通过设置TNMFTP.ProxyPort特性可以指定代理服务器端口。使用TIdFTP连接到FTP服务器Nevrona实现的Indy FTP组件TIdFTP支持的公开特性较少,但与TNMFTP基本相同。分别设置TIdFTP.Host、TIdFTP.Port、TIdFTP.User和TIdFTP.Password特性,并调用connect方

38、法,即可将FTP客户程序连接到FTP服务器。SimpleFTP.exe的第二种实现位于本书的光盘上。16.3.2 上传和下载文件FTP协议的首要目的在于提供客户与服务器之间的文件传输功能。您可能对TNMFTP了解较多,这里对两种FTP实现TNMFTP和TIdFTP进行了比较,使得您可以了解不同的实现风格。TNMFTP组件的文件传输方法TNMFTP.Upload和TNMFTP.Download方法都需要两个参数。上传是将文件从客户复制到服务器的过程,而下载刚好相反。两个方法的声明如下。procedure Download(RemoteFile, LocalFile: string);proced

39、ure Upload(LocalFile, RemoteFile: string)假定已经连接到FTP服务器,可以将要下载的服务器上文件的名字作为第一个参数,而本地计算机上保存的文件名作为第二个参数。如果目标文件在远程或本地计算机已经存在,相应的上传和下载过程将覆盖目标文件。文件传输是异步的。这样,对上传和下载方法的调用将在文件传输完成之前返回。文件传输的成功或失败,需要通过实现TNMFTP.OnSuccess和TNMFTP.OnFailure事件方法来进行通知。两个事件方法的Trans_Type参数类型都是TCmdType。例如,如果调用OnFailure方法而TCmdType参数是cmdD

40、ownload,则可以知道下载操作已经失败。TIdFTP组件的文件传输方法Indy的FTP实现中,下载方法命名为Get,上传方法命名为Put。Get实现为过载方法。procedure Get(const ASourceFile: string; ADest: TStream);overload;procedure Get(const ASourceFile: string; const ADestFile:string; const ACanOverwrite: boolean); overload;Get方法的第一个版本取得远程计算机上的源文件名,并把文件下载到TStream对象中。第二个版

41、本与TNMFTP的实现较为相似。第一和第二个参数分别表示远程和本地文件名,第三个参数指明在目标文件已经存在时是否覆盖。下面列出的代码示范了如何将文件下载到TStream对象中。varFileName : string;S : TStringStream;beginFileName := Copy( ListView1.Selected.Caption, LastDelimiter(' ',ListView1.Selected.Caption), 255 );S := TStringStream.Create('');tryif( Pos( '<DI

42、R>', ListView1.Selected.Caption ) = 0 ) thenIDFTP1.Get( FileName, S );S.Position := 0;Memo1.Lines.LoadFromStream(S);finallyS.Free;end;end;代码中有一些假定。第一个假定是TListView组件的Caption特性中包括文件名(在演示TIdFTP组件的SimpleFTP示例工程中确实如此,该工程在本书的光盘上),而且窗体上有一个名为Memo1的TMemo组件。代码将文件名从TListView组件中提取出来。然后创建TStringStream对象,T

43、StringStream是TStream的后代,因此我们可以对TIdFTP.Get方法的TStream参数使用TStringStream对象。将创建的流对象传递给Get方法。在调用Get方法后需要将流的位置重置为0,向流对象复制数据将改变流的当前位置。在装载了StringStream对象之后,可以使用TStrings.LoadFromStream方法将TStringStream对象中的数据复制到TMemo对象中(请记住,TMemo的Lines特性是一个TStrings类型的对象特性)。实现中过载了Put方法,以便直接在流对象和文件上进行工作(该实现是对称的,使得组件的使用非常直接。按照直觉,我

44、们可以认为,既然Get方法可以在流对象和文件上工作,那么,与之相对应的Put方法也应该能够在流对象和文件上工作)。Put方法的声明如下:procedure Put(const ASource: TStream; const ADestFile: string;const AAppend: boolean); overload;procedure Put(const ASourceFile: string; const ADestFile: string;const AAppend: boolean); overload;在Put的第一个实现中,该方法将数据从客户端的流对象复制到远程服务器上的文

45、件。如果AAppend参数设置为True,那么数据将附加在已存在的文件之后。在Put方法的第二个实现中,源数据和目标数据都是文件,而AAppend参数的作用与第一种实现相同。16.3.3 向FTP服务器发送命令FTP协议包含一个命令集,由大约20条命令组成。对于特定的组件而言,不见得把协议命令集中的每个命令都作为公有方法实现。通过使用一个一般性的方法向服务器发送命令字符串,可以支持在TIdFTP和TNMFTP组件的接口中并不直接支持的FTP命令。TIdFTP使用SendCmd方法实现了这种能力。function SendCmd(const AOut: string; const ARespon

46、se: SmallInt):SmallInt; virtual; overload;function SendCmd(const AOut: string; const AResponse: Array ofSmallInt): SmallInt; virtual; overload;在上述函数中,需要传递一个命令字符串和一个响应代码(或一组响应代码)。如果服务器的响应与响应代码并不匹配,将产生异常。在下面的代码片断中,使用响应代码150和226向FTP服务器发送了一个通常的list命令。如果服务器的响应不是150(打开连接)和226(传输完成),将产生异常。第二行代码将把缓冲区中的内容读入到

47、TString对象Dest中。IdFTP1.SendCmd('ls', 150, 226);Dest.Text := IdFTP1.CurrentReadBuffer;如果一个方法是可用的,则无需使用一般性的SendCmd方法。TIdFTP.List方法实现如下。procedure List(ADest: TStrings; const ASpecifier: string;const ADetails: boolean);第一个参数类型为TStrings,第二个参数不是文件掩码,而第三个参数表示返回文件信息。使用下述代码中的参数调用List,可以只返回文件名。varDest

48、: TStrings;beginDest : TStringList.Create;tryIDFtp1.List( Dest, '*.*', False );for I := 0 to Dest.Count - 1 dowith ListView1.Items.Add doCaption := DestI;finallyDest.Free;end;end;上面的代码向List传递了TStrings对象Dest和文件掩码*.*,而且不要求返回详细信息。for循环将字符串数组中的数据复制到名为ListView1的TListView组件中。提示:FTP协议定义在RFC 959中。幸运

49、的是,Indy和NetMaster FTP组件实现了许多通常的FTP命令,如上传和下载文件、建立和改变目录、删除和列出文件等。DoCommand是SendCmd方法的TNMFTP版本,该方法只有一个字符串参数,即所用的命令。对于FTP客户端的实现细节,请参见本书光盘上的FTPPro例子程序。16.4 创建Telnet客户程序终端仿真客户可以利用Telnet协议连接到Telnet服务器,通常使用端口23。尽管可以连接到其他的TCP/IP服务器,通常Telnet客户只用于连接到返回终端数据的服务器(参见John Ray的Special Edition Using TCP/IP一书,其中有一些有趣的

50、例子使用Telnet客户端连接到POP3和SMTP服务器)。本书光盘上的例子程序TelnetPro包含有演示Telnet客户端的源代码,该客户端模仿了Windows自带的Telnet.exe程序。找到仿真器所必须支持的ANSI代码的完整描述。ANSI代码的形式类似于$1B,即ASCII码27(十六进制$1B)所代表的Esc字符后接左方括号,其后是特定的字符串序列。图16.4 如图所示,使用TelnetPro.exe示例程序连接到密歇根州为完成终端仿真器,需要定义一个语法分析循环,用于从明文中提取ANSI转义代码,并根据ANSI代码确定何时删除显示内容、滚屏或修改显示字体。除了工作站上自带的很小

51、的Telnet客户端(可以通过Start | Run菜单运行)之外,NetM提供了Rumba。这两个产品演示了Telnet程序应具有的功能。使用TIdTelnet组件,需要指定主机和端口号。例如,将主机设置为,端口号设置为23,即可连接到MSU大学的MAGIC服务器。实现TIdTelnet.OnDataAvailable方法从字符串参数Buffer中读入服务器的响应。Buffer参数中包含了ANSI代码和要显示的文本。可使用SendCh或SendStr向服务器发送数据。SendCh每次通过Telnet端口发送一个字符,而SendStr每次向服务器传递一个字符串参数。下

52、面的示例代码捕获RichEdit控件中的击键事件,并按每次一个字符将其发送出去。procedure TFormMain.RichEdit1KeyPress(Sender: TObject; var Key:Char);constInput : string = ''beginif( Not IdTelnet1.Connected ) then exit;IdTelnet1.SendCh(Key);Key := #0;end;如果TIdTelnet组件并未连接到服务器,上面的代码将忽略key参数。否则,每次将向服务器发送一个字符,并把key参数设置为#0;这使得一直可以向Rich

53、Edit控件直接插入字符。下面列出的代码示范了一个简单的Telnet应用程序。unit UFormMain;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics,Controls, Forms,Dialogs, IdBaseComponent, IdComponent, IdTCPConnection,IdTCPClient,IdTelnet, StdCtrls, Menus;typeTFormMain = class(TForm)Memo1: TMemo;IdTelnet1: TIdTelnet;MainM

54、enu1: TMainMenu;Connect1: TMenuItem;Connect2: TMenuItem;Disconnect1: TMenuItem;N1: TMenuItem;Exit1: TMenuItem;procedure IdTelnet1DataAvailable(Buffer: String);procedure FormDestroy(Sender: TObject);procedure Memo1KeyPress(Sender: TObject; var Key: Char);procedure Exit1Click(Sender: TObject);procedur

55、e Connect2Click(Sender: TObject);procedure Disconnect1Click(Sender: TObject);procedure FormClose(Sender: TObject; var Action:TCloseAction);procedure FormCreate(Sender: TObject);private Private declarations public Public declarations end;varFormMain: TFormMain;implementation$R *.DFMprocedure TFormMai

56、n.IdTelnet1DataAvailable(Buffer: String);beginMemo1.Lines.Add(Buffer);end;procedure TFormMain.FormDestroy(Sender: TObject);beginIdTelnet1.Disconnect;end;procedure TFormMain.Memo1KeyPress(Sender: TObject; var Key:Char);beginif( IdTelnet1.Connected ) thenbeginif( Key = #13 ) then Memo1.Clear;IdTelnet1

57、.SendCh(Key);Key :=#0;end;end;procedure TFormMain.Exit1Click(Sender: TObject);beginClose;end;procedure TFormMain.Connect2Click(Sender: TObject);varHost : string;beginMemo1.Clear;Host := ''Disconnect1Click(Self);if( InputQuery( 'Host', 'Enter host address:', Host ) thenbeginIdTelnet1.Host := Host;IdTelnet1.Connect;end;end;procedure TFormMain.Disconnect1Click(Sender: TObject);beginif( IdTelnet1.Connected ) thenIdTelnet1.Disconnect;end

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论