利用Delphi编写Socket通信程序_第1页
利用Delphi编写Socket通信程序_第2页
利用Delphi编写Socket通信程序_第3页
利用Delphi编写Socket通信程序_第4页
利用Delphi编写Socket通信程序_第5页
已阅读5页,还剩31页未读 继续免费阅读

下载本文档

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

文档简介

1、Indy10Install All packages are followed by X0 (Where X is your Delphi verison).1. Download source from the Development Snapshot. Delphi / BCB Installation1. Open and compile in the following order: 2.1. IndySystem (in LibSystem) 2. IndyCore (in LibCore) 3. IndyProtocols (in LibProtocols) 4. IndySupe

2、rCore (in LibSuperCore)If you are not using SuperCore, then you do not need to compile this package. 3. Now open and click install in the following order 4.5.1. dclIndyCore (in LibCore) 2. dclIndyProtocols (in LibProtocols) 3. dclSuperCore (in LibSuperCore)Only install this if you have compiled Supe

3、rCore. 利用Delphi编写Socket通信程序2021-08-24 人气:5925 出处:csdn 作者: dudunono 原作 一、Delphi与Socket计算机网络是由一系列网络通信协议组成的,其中的核心协议是传输层的TCP/IP和UDP协议。TCP是面向连接的,通信双方保持一条通路,好比目前的 线,使用telnet登陆BBS,用的就是TCP协议;UDP是无连接的,通信双方都不保持对方的状态,浏览器访问Internet时使用的 协议就是基于UDP协议的。TCP和UDP协议都非常复杂,尤其是TCP协议,为了保证网络传输的正确性和有效性,必须进行一系列复杂的纠错和排序等处理。Soc

4、ket是建立在传输层协议(主要是TCP和UDP)上的一种套接字标准,最初是由美国加州Berkley大学提出,它定义两台计算机间进行通信的标准也是一种编程标准,如果说两台计算机是利用一个“通道“进行通信,那么这个“通道“的两端就是两个套接字。套接字屏蔽了底层通信软件和具体操作系统的差异,使得任何两台安装了TCP协议软件和实现了套接字标准的计算机之间的通信成为可能。微软的Windows Socket标准(简称winsock)对Berkley的套接字标准进行了扩展,利用标准的Socket的方法,可以同任何平台上的Socket进行通信;利用其扩展,可以更有效地实现在Windows平台上计算机间的通信。

5、在Delphi中,其底层的Socket也应该是Windows的Socket。Socket减轻了编写计算机间通信软件的难度,但总的说来还是相当复杂的这一点在后面具体会讲到;Inprise在Delphi中对Windows Socket进行了有效的封装,使得用户可以很方便地编写网络通信程序。下面我们实例解读在Delphi中如何利用Socket编写通信程序。二、利用Delphi编写Socket通信程序。下面是一个简单的Socket通信程序,其中客户机和效劳机是同一个程序,当客户机效劳器在一个memo1中输入一段文字然后敲入回车,该段文字就可以显示在效劳器(客户机)的memo2中,反之亦成立。具体步骤如

6、下:1、新建一个form,任意命名,不妨设之为chatForm;放上一个MainMenu(在Standard栏中),建立ListenItem、ConnectItem、Disconnect和Exit菜单项;在从Internet栏中选择TServerSocket、TClientSocket添加到chatForm中,其中把TClientSocket的名字设为ClientSocket, port设为1025,默认的active为false;把TServerSocket的名字设为ServerSocket,port设为1025,默认的active为false,其他的不变;再放入两个memo,一个命名为me

7、mo1,另外一个命名为memo2,其中把memo2的color设置为灰色,因为主要用来显示对方的输入。下面我们一边编写代码一边解释原因。、双击ListemItem。写入如下代码:procedure TChatForm.ListenItemClick(Sender: TObject);beginListenItem.Checked := not ListenItem.Checked;if ListenItem.Checked thenbeginClientSocket.Active := False;ServerSocket.Active := True;endelsebeginif Serve

8、rSocket.Active thenServerSocket.Active := False;end;end;该程序段的说明如下:当用户选择ListemItem时,该ListenItem取反,如果选中的话,说明处于Listen状态,读者要了解的是:listen是Socket作为Server时一个专有的方法,如果处于listen,那么ServerSocket设置为活动状态;否那么,取消listen,那么关闭ServerSocket。实际上,只有用户一开始选择该菜单项,说明该程序用作Server。反之,如果用户选择ConnectItem,那么必然作为Client使用。、双击ConnectItem

9、,敲入以下代码。procedure TChatForm.ConnectItemClick(Sender: TObject);beginif ClientSocket.Active then ClientSocket.Active := False;if InputQuery('Computer to connect to', 'Address Name:', Server) thenif Length(Server) > 0 thenwith ClientSocket dobeginHost := Server;Active := True;ListenI

10、tem.Checked := False;end;end;这段程序的主要功能就是当用户选择ConnectItem菜单项时,设置应用程序为客户机,弹出input框,让用户输入效劳器的地址。这也就是我们不一开始固定ClientSocket的host的原因,这样用户可以动态地连接不同的效劳器。读者需要了解的是主机地址只是Socket作为客户机时具有的一个属性,Socket作为效劳器时“一般“不用地址,因为它同本机绑定。4、在memo1的keydown方法中写入如下代码:procedure TChatForm.Memo1KeyDown(Sender: TObject; var Key: Word;Sh

11、ift: TShiftState);beginif Key = VK_Return thenif IsServer thenelseend;该段代码的作用很明显,就是开始发消息了。其中如果是Server的话,它只向第一个客户机发消息,由于一个效劳器可以连接多个客户机,而同客户机的每一个连接都由一个Socket来维Socket,而发送、接受消息的方法分别为send(sendto)和recv(recvfrom), Delphi对此进行了封装。、其余代码的简要介绍。procedure TChatForm.ServerSocketAccept(Sender: TObject;Socket: TCust

12、omWinSocket);beginIsServer := True;end;ServerSocket的Accept方法,当客户机第一次连接时完成,通过其参数可以认为,它是在标准的accept方法后执行的,因为有TCustomWinSocket这个参数类型,它应该是标准Server方Socket的返回值。 procedure TChatForm.ClientSocketRead(Sender: TObject;Socket: TCustomWinSocket);beginend;procedure TChatForm.ServerSocketClientRead(Sender: TObject

13、;Socket: TCustomWinSocket);beginend;这两段代码分别是效劳器方和客户机方在收到对方的消息时,由Delphi触发的,作用是在memo2中显示收到的消息。其中,ClientSocketRead中的Socket实际上就是Socket本身,而在procedure TChatForm.ServerSocketClientConnect(Sender: TObject;Socket: TCustomWinSocket);beginend;procedure TChatForm.ClientSocketDisconnect(Sender: TObject;Socket: T

14、CustomWinSocket);beginListenItemClick(nil);end;这两段比拟简单。其中ServerSocketClientConnect在ServerSocket收到一个新的连接时触发。而ClientSocketDisconnect在ClientSocket发出Disconncet时触发。procedure TChatForm.Exit1Click(Sender: TObject);beginServerSocket.Close;ClientSocket.Close;Close;end;procedure TChatForm.Disconnect1Click(Sen

15、der: TObject);beginClientSocket.Active := False;ServerSocket.Active := True;end;定调用了closesocket方法。三、标准Socket与Delphi中的Socket。标准的Socket的应用程序框架如下:Server方: Socket() 新建一个SocketBind() 同效劳器地址邦定 Listen() Accept()block waitread()接受消息,在windows平台中,方法为send(TCP),或者是sendto(UDP)处理效劳请求Write()发送消息,在windows平台中,方法为sen

16、d(TCP), 或者为sendto(UDP)。Client方相对简单:Socket()Connect()通过一定的port连接特定的效劳器,这是与效劳器建立连接Write()Read()。Socket可以是基于TCP的,也可以是基于UDP,同时Socket甚至建立在其他的协议,比方IPX/SPX,DECNet等。在新建一个Socket时,可以指定新建何类Socket。Bind()用来同效劳器的地址邦定,如果一个主机只有一个IP地址,实际上邦定的作用就相对多余了。Listen()开始监听网络,Accept()用于接受连接,其返回值是保持同客户机联系的Socket。在Delphi中,对于Windo

17、ws中的Socket进行了有效的封装。在Delphi中,按其继承关系,可以分层两类:一、TComponentTAbstractSocketTCustomSocketTCustomServerSocketTServerSocketTComponentTAbstractSocketTCustomSocketTClientSocket二、直接从TObject继承过来:TObjectTCustomWinSocketTServerWinSocketTObjectTCustomWinSocketTClientWinSocketTObjectTCustomWinSocketTServerClientWinS

18、ocket可以看出第一类建立在TCustomSocket根底上,第二类建立在TCustomWinSocket的根底上。第一类建立在TComponet的根底上,第二类直接构建在TObject根底上。因此如果用户非常熟悉Socket并且想要编写控制台程序时,可以使用TCustomWinScoket类。同uses中可以看出,它们都在ScktComp.pas中实现,而在schtComp.pas中,那么包含了winsock.pas文件,如果继续深入winsock文件,在其中可以发现所有的Windows Socket的根本方法。实际上,如果你了解了标准Socket的应用程序框架,对于使用Delphi编写S

19、ocket应用程序也就得心应手了;这不是说你必须了解复杂的Socket中的标准函数,也没有必要,因为Delphi已经为你做了很好的封装了,这也正是Delphi的强势所在,你只要了解那么一点点的根本框架。这是我对Delphi中的Socket应用的理解,缺乏之处希望大家指正。同时也乐于为大家解答Delphi中有关Socket的问题。用Indy组件开发Socket应用程序 创立时间:2021-3-16文章属性:转载文章提交:绝对零度今日浏览:23总共次数:648 文章 虚度文章出处:yesky 笔者在前一段的工作中,需要开发一套简单的网络数据传输程序。由于平时常用Delphi做点开发,故此次也不例外

20、。Delphi 7中带有两套TCP Socket组件:Indy Socket组件IdTCPClient和IdTCPServer和Delphi原生的TCP Socket组件ClientSocket和ServerSocket。但是,Borland已宣称ClientSocket和ServerSocket组件即将被废弃,建议用相应的Indy组件来代替。因此,笔者使用了Indy。本文在对Indy进行简要介绍的根底上,创立了一组简单的TCP Socket数据传输应用来演示了Indy的使用方法。开放源代码的Internet组件集Internet DirectIndyInternet DirectIndy是一

21、组开放源代码的Internet组件,涵盖了几乎所有流行的Internet协议。Indy用Delphi编写,被包含在Delphi 6,Kylix 1和C+ Builder 6及以上各个版本的Borland开发环境中。Indy曾经叫做WinShoes双关于WinSockWindows的Socket库,是由Chad Z. Hower领导的一群开发者Delphi 7中所带的是Indy 9。在其的组件面板上,一共安装有100多个Indy组件。使用这些组件你可以开发基于各种协议的TCP客户和效劳器应用程序,并处理相关的编码和平安问题。你可以通过前缀Id来识别Indy组件。Indy是阻塞式Blocking的

22、当你使用Winsock开发网络应用程序时,从Socket中读取数据或者向Socket写入数据都是异步发生的,这样就不会阻断程序中其它代码的执行。在收到数据时,Winsock会向应用程序发送相应的消息。这种访问方式被称作非阻塞式连接,它要求你对事件作出响应,设置状态机,并通常还需要一个等待循环。与通常的Winsock编程方法不同的是,Indy使用了阻塞式Socket调用方式。阻塞式访问更像是文件存取。当你读取数据,或是写入数据时,读取和写入函数将一直等到相应的操作完成后才返回。比方说,发起网络连接只需调用Connect方法并等待它返回,如果该方法执行成功,在结束时就直接返回,如果未能成功执行,那

23、么会抛出相应的异常。同文件访问不同的是,Socket调用可能会需要更长的时间,因为要读写的数据可能不会立即就能准备好在很大程度上依赖于网络带宽。阻塞式Socket并非恶魔Evil长期以来,阻塞式Socket都遭到了毫无理由的攻击。其实阻塞式Socket并非如通常所说的那样可怕。这还要从Winsock的开展说起。当Socket被从Unix移植到Windows时,一个严重的问题立即就出现了。Unix支持fork,客户程序和效劳器都能够fork新的进程,并启动这些进程,从而能够很方便地使用阻塞式Socket。而Windows 3.x既不支持fork也不支持多线程,当使用阻塞式Socket时,用户界面

24、就会被“锁住而无法响应用户输入。为克服Windows 3.x的这一缺陷,微软在Winsock中参加了异步扩展,以使Winsock不会“锁住应用程序的主线程也是唯一的线程。然而,这需要了一种完全不同的编程方式。于是有些人为了掩饰这一弱点,就开始强烈地诽谤阻塞式Socket。当Win32出现的时候,它能够很好地支持线程。但是既成的观念已经很难更改,并且说出去的话也无法收回,因此对阻塞式Socket的诽谤继续存在着。事实上,阻塞式Socket仍然是Unix实现Socket的唯一方式,并且它工作得很好。阻塞式Socket的优点归结起来,在Windows上使用阻塞式Socket开发应用程序具有如下优点:

25、编程简单阻塞式Socket应用程序很容易编写。所有的用户代码都写在同一个地方,并且顺序执行。 容易向Unix移植由于Unix也使用阻塞式Socket,编写可移植的代码就变得比拟容易。Indy就是利用这一点来实现其多平台支持而又单一源代码的设计。 很好地利用了线程技术阻塞式Socket是顺序执行的,其固有的封装特性使得它能够很容易地使用到线程中。 阻塞式Socket的缺点事物都具有两面性,阻塞式Socket也不例外。它的一个主要的缺点就是使客户程序的用户界面“冻结。当在程序的主线程中进行阻塞式Socket调用时,由于要等待Socket调用完成并返回,这段时间就不能处理用户界面消息,使得Updat

26、e、Repaint以及其它消息得不到及时响应,从而导致用户界面被“冻结。使用TIdAntiFreeze对抗“冻结Indy使用一个特殊的组件TIdAntiFreeze来透明地解决客户程序用户界面“冻结的问题。TIdAntiFreeze在Indy内部定时中断对栈的调用,并在中断期间调用Application.ProcessMessages方法处理消息,而外部的Indy调用继续保存阻塞状态,就好似TIdAntiFreeze对象不存在一样。你只要在程序中的任意地方添加一个TIdAntiFreeze对象,就能在客户程序中利用到阻塞式Socket的所有优点而避开它的一些显著缺点。Indy使用了线程技术阻塞

27、式Socekt通常都采用线程技术,Indy也是如此。从最底层开始,Indy的设计都是线程化的。因此用Indy创立效劳器和客户程序跟在Unix下十分相似,并且Delphi的快速开发环境和Indy对WinSock的良好封装使得应用程序创立更加容易。Indy效劳器模型一个典型的Unix效劳器有一个或多个监听进程,它们不停地监听进入的客户连接请求。对于每一个需要效劳的客户,都fork一个新进程来处理该客户的所有事务。这样一个进程只处理一个客户连接,编程就变得十分容易。Indy效劳器工作原理同Unix效劳器十分类似,只是Windows不像Unix那样支持fork,而是支持线程,因此Indy效劳器为每一个

28、客户连接分配一个线程。图1显示了Indy效劳器的工作原理。Indy效劳器组件创立一个同应用程序主线程别离的监听线程来监听客户连接请求,对于接受的每一个客户,都创立一个新的线程来为该客户提供效劳,所有与这一客户相关的事务都由该线程来处理。使用组件TIdThreadMgrPool,Indy还支持线程池。 上一页 1 2 3 4 下一页线程与Indy客户程序Indy客户端组件并未使用线程。但是在一些高级的客户程序中,程序员可以在自定义的线程中使用Indy客户端组件,以使用户界面更加友好。简单的Indy应用例如下面将创立一个简单的TCP客户程序和一个简单的TCP效劳器来演示Indy的根本使用方法。客户

29、程序使用TCP协议同效劳器连接,并向效劳器发送用户所输入数据。效劳器支持两条命令:DATA和QUIT。在DATA命令后跟随要发送的数据,并用空格将命令字DATA和数据分隔开。表单布局建立一个工程组,添加一个客户程序工程和一个效劳器工程。客户程序和效劳器程序的表单布局如同2和图3所示。客户程序表单上放置了TIdTCPClient组件,效劳器程序表单上放置了TIdTCPServer组件。为防止客户程序“冻结,还在其表单上放置TIdAntiFreeze组件。客户程序和效劳器程序的表单上都放置有TListBox组件,用来显示通信记录。客户程序代码客户程序片断如代码列表1所示。代码列表1procedur

30、e TFormMain.BtnConnectClick(Sender: TObject);beginIdTCPClient.Host := EdtHost.Text;IdTCPClient.Port := StrToInt(EdtPort.Text);with IdTCPClient dobegintryConnect(5000);tryBtnConnect.Enabled := False;BtnSend.Enabled := True;BtnDisconnect.Enabled := True;exceptIdTCPClient.Disconnect();end;/end tryexcep

31、tend;/end tryend;/end withend;procedure TFormMain.BtnSendClick(Sender: TObject);beginwith IdTCPClient dobegintryWriteLn('DATA ' + EdtData.Text);exceptIdTCPClient.Disconnect();BtnConnect.Enabled := True;BtnSend.Enabled := False;BtnDisconnect.Enabled := False;end;/end tryend;/end withend;proce

32、dure TFormMain.BtnDisconnectClick(Sender: TObject);varReceived: string;begintryIdTCPClient.WriteLn('QUIT');finallyIdTCPClient.Disconnect();BtnConnect.Enabled := True;BtnSend.Enabled := False;BtnDisconnect.Enabled := False;end;/end tryend; 在“连接按钮事件响应过程中,首先根据用户输入设置IdTCPClient的主机和端口,并调用IdTCPCli

33、ent的Connect方法向效劳器发出连接请求。然后调用ReadLn方法读取效劳器应答数据。在“发送按钮事件响应过程中,调用WriteLn方法写DATA命令,向效劳器发送数据。在“断开按钮事件响应过程中,向效劳器发送QUIT命令,并调用Disconnect方法断开连接。程序中还包含有通信信息记录和异常处理的代码。效劳器程序代码效劳器程序片断如代码列表2所示。代码列表2procedure TFormMain.BtnStartClick(Sender: TObject);beginIdTCPServer.DefaultPort := StrToInt(EdtPort.Text);IdTCPServ

34、er.Active := True;BtnStart.Enabled := False;BtnStop.Enabled := True;end;procedure TFormMain.BtnStopClick(Sender: TObject);beginIdTCPServer.Active := False;BtnStart.Enabled := True;BtnStop.Enabled := False;end;procedure TFormMain.IdTCPServerConnect(AThread: TIdPeerThread);begin+ ' 的连接请求已被接纳!'

35、);end;procedure TFormMain.IdTCPServerExecute(AThread: TIdPeerThread);varsCommand: string;beginwith AThread.Connection dobeginsCommand := ReadLn();FLogEntry := sCommand + ' 来自于主机 'AThread.Synchronize(AddLogEntry);if AnsiStartsText('DATA ', sCommand) thenbeginFReceived := RightStr(sCom

36、mand, Length(sCommand)-5);WriteLn('200: 数据接收成功!');AThread.Synchronize(DisplayData);endelse if SameText(sCommand, 'QUIT') then beginFLogEntry := '断开同主机 '+ ' 的连接!'AThread.Synchronize(AddLogEntry);Disconnect;endelse beginWriteLn('500: 无法识别的命令!');FLogEntry := '

37、;无法识别命令:' + sCommand;AThread.Synchronize(AddLogEntry);end;/endifend;end;procedure TFormMain.DisplayData();beginEdtData.Text := FReceived;end;procedure TFormMain.AddLogEntry();beginend; “启动按钮设置IdTCPServer 的Active属性为True来启动效劳器,“停止按钮设置Active属性为False来关闭效劳器。IdTCPServerConnect方法作为IdTCPServer 的OnCorrec

38、t事件响应过程,向客户端发送欢送信息。OnCorrect事件在一个客户连接请求被接受时发生,为该连接创立的线程AThread被作为参数传递给IdTCPServerConnect方法。IdTCPServerExecute方法是IdTCPServer 的OnExecute事件响应过程。OnExecute事件在TIdPeerThread对象试图执行其Run方法时发生。OnExecute事件与通常的事件有所不同,其响应过程是在某个线程上下文中执行的,参数AThread就是调用它的线程。这一点很重要,它意味着可能有多个OnExecute事件响应过程被同时执行。在连接被断开或中断前,OnExecute事件

39、响应过程会被反复执行。在IdTCPServerExecute方法中,首先读入一条指令,然后对指令进行判别。如果是DATA指令,就解出数据并显示它。如果收到的是QUIT指令,那么断开连接。需要特别指出的是,由于IdTCPServerExecute方法在某一线程上下文中执行,因此显示数据和添加事件记录都是将相应的方法传递给Synchronize调用来完成的。运行程序运行客户端和效劳器程序,按如下流程进行操作:1. 按效劳器程序的“启动按钮启动效劳器;2. 按客户程序的“连接按钮,建立同效劳器的连接;3. 在客户程序的待发送数据编辑框中输入“Hello, Indy!,并按“发送按钮发送数据;4. 按

40、客户程序的“断开按钮,断开同效劳器的连接;5. 按效劳器程序的“停止按钮停止效劳器。 用Socket接收和转换数字和字符串数据【大 中 小】【打印】【参加收藏】【关闭】浏览字号:日期:2022-06-13 人气:60 出处:codeguru 作者: 7nightlove 很多时候远程系统在执行并发任务的时候,会把它接收到数据的长度以数字的形式发送出去。但用socket发送和接收数字型数据的时候,要考虑到一个问题:要根据网络另一端机器的类型转换数据。尤其需要知道怎样把要发送的数据格式网络格式从本地机器的格式主机格式转换成为行业标准格式。 使用IPAddress.NetworkToHostOrde

41、r可以把数据从网络规那么转换为主机格式,下面的ReceiveHeader函数说明了它的用法,ReceiveHeader函数实现过程如下:1 用Socket.Receive从远程机器接收数据。 2 验证接收到的字节数是4。3 Socket.Receive返回一个字节型数组,BitConvert.ToInt32把它转换成数字型数值。4 最后,IPAddress.NetworkToHostOrder把长数值转换为主机格式。public int ReceiveHeader(Socket socket) int dataSize = -1; / error byte buffer = new byte4

42、; int bytesRead = socket.Receive(buffer, 4, if (4 = bytesRead) dataSize = BitConverter.ToInt32(buffer, 0); dataSize = IPAddress.NetworkToHostOrder(dataSize); else / error condition return dataSize; 下面再来看一下怎样用多线程读取的方法为每个字符串都建立连接,从远程机器接收字符串型数据。在这种情况下,要把字节型数据转换成String型对象。你可以根据需要用ASCIIEncoding或UnicodeEn

43、coding类进行转换。ReceiveDetail函数按以下步骤实现此函数必须在ReceiveHeader后调用,因为datasize的值是从ReceiveHeader中得到的。1 在while循环中调用Socket.Receive,直到无返回值为止。数据被读入一个字节型数组。2 建立一个ASCIIEncoding对象。3 调用ASCIIEncoding.GetString把字节型数组转换成String对象,然后把它和先前读入的数据连接。public string ReceiveDetail(Socket socket, byte buffer, int dataSize) string re

44、sponse = "" int bytesReceived = 0; int totalBytesReceived = 0; while (0 < (bytesReceived = socket.Receive(buffer, (dataSize - totalBytesReceived), SocketFlags.None) totalBytesReceived += bytesReceived; ASCIIEncoding encoding = new ASCIIEncoding(); response += encoding.GetString(buffer,

45、0, bytesReceived); return response;在Delphi 7 中用Indy开发Socket应用程序 2021-11-26 14:13:55 虚度 笔者在前一段的工作中,需要开发一套简单的网络数据传输程序。由于平时常用Delphi做点开发,故此次也不例外。Delphi 7中带有两套TCP Socket组件:Indy Socket组件IdTCPC lient和IdTCPServer和Delphi原生的TCP Socket组件ClientSocket和ServerSocket。但是,Borland已宣称ClientSocket和ServerSocket组件即将被废弃,建议

46、用相应的Indy组件来代替。因此,笔者使用了Indy。本文在对Indy进行简要介绍的根底上,创立了一组简单的TCP Socket数据传输应用来演示了Indy的使用方法。开放源代码的Internet组件集Internet DirectIndyInternet DirectIndy是一组开放源代码的Internet组件,涵盖了几乎所有流行的Internet协议。Indy用Delphi编写,被包含在Delphi 6,Kylix 1和C+ Builder 6及以上各个版本的Borland开发环境中。Indy曾经叫做WinShoes双关于WinSockDelphi 7中所带的是Indy 9。在其的组件面

47、板上,一共安装有100多个Indy组件。使用这些组件你可以开发基于各种协议的TCP客户和效劳器应用程序,并处理相关的编码和平安问题。你可以通过前缀Id来识别Indy组件。Indy是阻塞式Blocking的当你使用Winsock开发网络应用程序时,从Socket中读取数据或者向Socket写入数据都是异步发生的,这样就不会阻断程序中其它代码的执行。在收到数据时,Winsock会向应用程序发送相应的消息。这种访问方式被称作非阻塞式连接,它要求你对事件作出响应,设置状态机,并通常还需要一个等待循环。与通常的Winsock编程方法不同的是,Indy使用了阻塞式Socket调用方式。阻塞式访问更像是文件

48、存取。当你读取数据,或是写入数据时,读取和写入函数将一直等到相应的操作完成后才返回。比方说,发起网络连接只需调用Connect方法并等待它返回,如果该方法执行成功,在结束时就直接返回,如果未能成功执行,那么会抛出相应的异常。同文件访问不同的是,Socket调用可能会需要更长的时间,因为要读写的数据可能不会立即就能准备好在很大程度上依赖于网络带宽。阻塞式Socket并非恶魔Evil长期以来,阻塞式Socket都遭到了毫无理由的攻击。其实阻塞式Socket并非如通常所说的那样可怕。这还要从Winsock的开展说起。当Socket被从Unix移植到Windows时,一个严重的问题立即就出现了。Uni

49、x支持fork,客户程序和效劳器都能够fork新的进程,并启动这些进程,从而能够很方便地使用阻塞式Socket。而Windows 3.x既不支持fork也不支持多线程,当使用阻塞式Socket时,用户界面就会被“锁住而无法响应用户输入。为克服Windows 3.x的这一缺陷,微软在Winsock中参加了异步扩展,以使Winsock不会“锁住应用程序的主线程也是唯一的线程。然而,这需要了一种完全不同的编程方式。于是有些人为了掩饰这一弱点,就开始强烈地诽谤阻塞式Socket。当Win32出现的时候,它能够很好地支持线程。但是既成的观念已经很难更改,并且说出去的话也无法收回,因此对阻塞式Socket

50、的诽谤继续存在着。事实上,阻塞式Socket仍然是Unix实现Socket的唯一方式,并且它工作得很好。阻塞式Socket的优点归结起来,在Windows上使用阻塞式Socket开发应用程序具有如下优点: 编程简单阻塞式Socket应用程序很容易编写。所有的用户代码都写在同一个地方,并且顺序执行。 容易向Unix移植由于Unix也使用阻塞式Socket,编写可移植的代码就变得比拟容易。Indy就是利用这一点来实现其多平台支持而又单一源代码的设计。 很好地利用了线程技术阻塞式Socket是顺序执行的,其固有的封装特性使得它能够很容易地使用到线程中。阻塞式Socket的弱点事物都具有两面性,阻塞式

51、Socket也不例外。它的一个主要的缺点就是使客户程序的用户界面“冻结。当在程序的主线程中进行阻塞式Socket调用时,由于要等待Socket调用完成并返回,这段时间就不能处理用户界面消息,使得Update、Repaint以及其它消息得不到及时响应,从而导致用户界面被“冻结。使用TIdAntiFreeze对抗“冻结Indy使用一个特殊的组件TIdAntiFreeze来透明地解决客户程序用户界面“冻结的问题。TIdAntiFreeze在Indy内部定时中断对栈的调用,并在中断期间调用Application.ProcessMessages方法处理消息,而外部的Indy调用继续保存阻塞状态,就好似T

52、IdAntiFreeze对象不存在一样。你只要在程序中的任意地方添加一个TIdAntiFreeze对象,就能在客户程序中利用到阻塞式Socket的所有优点而避开它的一些显著缺点。Indy使用了线程技术阻塞式Socekt通常都采用线程技术,Indy也是如此。从最底层开始,Indy的设计都是线程化的。因此用Indy创立效劳器和客户程序跟在Unix下十分相似,并且Delphi的快速开发环境和Indy对WinSock的良好封装使得应用程序创立更加容易。Indy效劳器模型一个典型的Unix效劳器有一个或多个监听进程,它们不停地监听进入的客户连接请求。对于每一个需要效劳的客户,都fork一个新进程来处理该

53、客户的所有事务。这样一个进程只处理一个客户连接,编程就变得十分容易。Indy效劳器工作原理同Unix效劳器十分类似,只是Windows不像Unix那样支持fork,而是支持线程,因此Indy效劳器为每一个客户连接分配一个线程。图1显示了Indy效劳器的工作原理。Indy效劳器组件创立一个同应用程序主线程别离的监听线程来监听客户连接请求,对于接受的每一个客户,都创立一个新的线程来为该客户提供效劳,所有与这一客户相关的事务都由该线程来处理。使用组件TIdThreadMgrPool,Indy还支持线程池。图1 Indy效劳器工作原理线程与Indy客户程序Indy客户端组件并未使用线程。但是在一些高级

54、的客户程序中,程序员可以在自定义的线程中使用Indy客户端组件,以使用户界面更加友好。简单的Indy应用例如下面将创立一个简单的TCP客户程序和一个简单的TCP效劳器来演示Indy的根本使用方法。客户程序使用TCP协议同效劳器连接,并向效劳器发送用户所输入数据。效劳器支持两条命令:DATA和QUIT。在DATA命令后跟随要发送的数据,并用空格将命令字DATA和数据分隔开。表单布局建立一个工程组,添加一个客户程序工程和一个效劳器工程。客户程序和效劳器程序的表单布局如同2和图3所示。客户程序表单上放置了TIdTCPClient组件,效劳器程序表单上放置了TIdTCPServer组件。为防止客户程序“冻结,还在其表单上放置TIdAntiFreeze组件。客户程序和效劳器程序的表单上都放置有TListBox组件,用来显示通信记录。图2 简单的TCP客户程序表单图3 简单的TCP效劳器程序表单在Delphi 7 中用Indy开发Socket应用程序虚度2021-11-26 14:13:55客户程序代码客户程序片断如代码列表1所示。代码列表1procedure TFormMain.BtnConnectClick(Sender: TObject);beginIdTCPClient.Host := EdtHost.Text;IdTCPClient.Port

温馨提示

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

评论

0/150

提交评论