


版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、Indy10InstallAll 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. IndySuperCore
2、(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 order4.5.1. dclIndyCore (in LibCore)2. dclIndyProtocols (in LibProtocols)3. dclSuperCore (in LibSuperCore)Only install this if you have compiled SuperCore.利用 D
3、elphi 编写 Socket 通信程序2004-08-24 人气: 5925 出处: csdn 作者 : dudunono 原作 一、Delphi 与 Socket计算机网络是由一系列网络通信协议组成的,其中的核心协议是传输层的TCP/IP和UDP协议。TCP是面向连接的,通信双方保持一条通路,好比目前的电话线,使用telnet登陆BBS,用的就是TCP协议;UDP是无连接的,通信双方都不保持对方的状态,浏览器访问Internet时使用的HTTP协议就是基于UDP协议的。TCP和UDP协议都非常复杂,尤其是 TCP协议,为了保证网络传输的正确性和有效性,必须进行一系列复杂的纠错和排序等处理。
4、Socket是建立在传输层协议(主要是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中输入一段文字然后敲入回车,该段文字就可以
6、显示在服务器(客户机)的memo2中,反之亦成立。具体步骤如下:1、新建一个form,任意命名,不妨设之为 chatForm ;放上一个 MainMenu(在Standard 栏中),建立 ListenItem 、 ConnectItem 、 Disconnect 和 Exit 菜单项;在从 Internet 栏中选择TServerSocket 、TClientSocket 添加到 chatForm 中,其中把 TClientSocket 的名字设为 ClientSocket, port 设为 1025,默认的 active 为 false ;把 TServerSocket 的名字设为 Ser
7、verSocket ,port设为1025,默认的active 为false,其他的不变;再放入两个memo 个命名为 memo1另外一个命名为memo2其中把memo2的 color设置为灰色,因为主要用来显示对方的输入。下面我们一边编写代码一边解释原因2、双击Listemltem。写入如下代码:procedure TChatForm.ListenItemClick(Sender: TObject);beginListenltem.Checked := not Listenltem.Checked;if Listenltem.Checked thenbeginClientSocket.Act
8、ive := False;ServerSocket.Active := True;endelsebeginif ServerSocket.Active thenServerSocket.Active := False;end;end;该程序段的说明如下: 当用户选择 Listemltem 时,该 Listenltem 取反,如果选中的话, 说明处于 Listen 状态,读者要了解的是: listen 是 Socket 作为 Server 时一个专有的方法,如果处于listen, 则 ServerSocket 设置为活动状态;否则,取消 listen ,则关闭 ServerSocket 。实际上
9、,只有用户 一开始选择该菜单项,表明该程序用作 Server 。反之,如果用户选择 Connectltem ,则必然作为 Client 使用。3、双击 Connectitem,敲入以下代码。procedure TChatForm.ConnectltemClick(Sender: TObject);beginif ClientSocket.Active then ClientSocket.Active := False;if lnputQuery('Computer to connect to', 'Address Name:', Server) thenif L
10、ength(Server) > 0 thenwith ClientSocket dobeginHost := Server;Active := True;Listenltem.Checked := False;end;end;这段程序的主要功能就是当用户选择 Connectltem 菜单项时, 设置应用程序为客户机, 弹出 input 框, 让用户输入服务器的地址。这也就是我们不一开始固定 ClientSocket 的 host 的原因,这样用户可以动态地连接不同的服务器。 读者需要了解的是主机地址只是 Socket 作为客户机时具有的一个 属性, Socket 作为服务器时“一般“不用
11、地址,因为它同本机绑定。4、在 memol的keydown方法中写入如下代码:procedure TChatForm.Memo1KeyDown(Sender: TObject; var Key: Word;Shift: TShiftState);beginif Key = VK_Return thenif IsServer thenServerSocket.Socket.Connections0.SendText(Memo1.LinesMemo1.Lines.Count - 1)elseClientSocket.Socket.SendText(Memo1.LinesMemo1.Lines.Co
12、unt - 1); end;该段代码的作用很明显,就是开始发消息了。其中如果是 Server 的话,它只向第一个客户机发消息, 由于一个服务器可以连接多个客户机,而同客户机的每一个连接都由一个 Socket 来维持,因此 ServerSocket.Socket.Connnections 数组中存储的就是同 Client 维持连接的 Socket 。在标准 Socket 中,服务器方的 Socket 通过 accept() 方法的返回值获取维持同客户机连接的Socket, 而发送、接受消息的方法分别为 send(sendto) 和 recv(recvfrom), Delphi 对此进行了封装。5
13、、其余代码的简要介绍。procedure TChatForm.ServerSocketAccept(Sender: TObject;Socket: TCustomWinSocket);beginIsServer := True;end;ServerSocket 的 Accept 方法,当客户机第一次连接时完成, 通过其参数可以认为, 它是在标准的 accept 方法后执行的,因为有 TCustomWinSocket 这个参数类型,它应该是标准 Server 方Socket 的返回值。procedure TChatForm.ClientSocketRead(Sender: TObject;Soc
14、ket: TCustomWinSocket);beginMemo2.Lines.Add(Socket.ReceiveText);end;procedure TChatForm.ServerSocketClientRead(Sender: TObject;Socket: TCustomWinSocket);beginMemo2.Lines.Add(Socket.ReceiveText); end;这两段代码分别是服务器方和客户机方在收到对方的消息时,由Delphi触发的,作用是在memo冲显示收到的消息。其中, ClientSocketRead 中的 Socket 实际上就是 Socket 本身
15、,而在ServerSocketClientRead 中的 Socket 实际上是 ServerSocket.Socket.Connection 中的某个 Socket 。不 过在 Delphi 中,对服务器方的 Socket 进行了有效的封装。procedure TChatForm.ServerSocketClientConnect(Sender: TObject;Socket: TCustomWinSocket);beginMemo2.Lines.Clear;end;procedure TChatForm.ClientSocketDisconnect(Sender: TObject;Sock
16、et: TCustomWinSocket);beginListenItemClick(nil);end;这两段比较简单。其中 ServerSocketClientConnect 在 ServerSocket 收到一个新的连接时触发。而 ClientSocketDisconnect 在 ClientSocket 发出 Disconncet 时触发。procedure TChatForm.Exit1Click(Sender: TObject);beginServerSocket.Close;ClientSocket.Close;Close;end;procedure TChatForm.Disco
17、nnect1Click(Sender: TObject);beginClientSocket.Active := False;ServerSocket.Active := True;end;第一段为关闭应用程序。在标准 Socket 中,每个 Socket 在关闭时,必须调用 closesocket() 方法, 否则系统不会释放资源。而在 ServerSockt.Close 和 ClientSocket.Close 中,系统内部肯定调用了 closesocket ()方法。三、标准 Socket 与 Delphi 中的 Socket 。标准的 Socket 的应用程序框架如下:Server 方
18、: Socket() 新建一个 Socket Bind()同服务器地址邦定 Listen() Accept() block wait read() 接受消息,在 windows 平台中,方法为 send(TCP), 或者是sendto(UDP) 处理服务请求 Write() 发送消息,在 windows 平台中,方法为 send(TCP), 或者为 sendto(UDP) 。Client 方相对简单: Socket() Connect() 通过一定的 port 连接特定的服务器,这是与服务器建立连 接 Write() Read() 。Socket可以是基于 TCP的,也可以是基于 UDP,同时
19、Socket甚至建立在其他的协议,比如IPX/SPX,DECNet等。在新建一个Socket时,可以指定新建何类 Socket。Bind()用来同服务器的地址邦定,如果一个主机只有一个 IP 地址,实际上邦定的作用就相对多余了。 Listen() 开始监听网络, Accept() 用于接受连接,其返回值是保持同客户机联系的 Socket。在Delphi中,对于 Windows中的Socket进行了有效的封装。在 Delphi中,按其继承关系,可以分层 两类:一、TComponentTAbstractSocketTCustomSocketTCustomServerSocketTServerSoc
20、ketTComponent TAbstractSocket TCustomSocket TClientSocket二、直接从 TObject 继承过来 :TObject TCustomWinSocket TServerWinSocketTObject TCustomWinSocket TClientWinSocketTObject TCustomWinSocket TServerClientWinSocket可以看出第一类建立在 TCustomSocket 基础上, 第二类建立在 TCustomWinSocket 的基础上。 第一类建 立在TComponet的基础上,第二类直接构建在TObje
21、ct基础上。因此如果用户非常熟悉Socket 并且想要编写控制台程序时,可以使用 TCustomWinScoket 类。同 uses 中可以看出,它们都在 ScktComp.pas 中实现,而在 schtComp.pas 中,则包含了 winsock.pas 文件,如果继续深入 winsock 文件,在其中可以发现所有的 Windows Socket 的基本方法。实际上, 如果你了解了标准 Socket 的应用程序框架, 对于使用 Delphi 编写 Socket 应用程序也就得心 应手了;这不是说你必须了解复杂的Socket 中的标准函数,也没有必要,因为 Delphi 已经为你做了很好的封
22、装了,这也正是Delphi 的强势所在,你只要了解那么一点点的基本框架。这是我对 Delphi 中的 Socket 应用的理解, 不足之处希望大家指正。 同时也乐于为大家解答 Delphi 中 有关 Socket 的问题。用 Indy 组件开发 Socket 应用程序创建时间: 2004-3-16 文章属性:转载 文章提交:绝对零度今日浏览: 23总共次数: 648文章作者:虚度文章出处: yesky笔者在前一段的工作中, 需要开发一套简单的网络数据传输程序。由于平时常用 Delphi 做点开发, 故 此次也不例外。 Delphi 7 中带有两套 TCP Socket 组件: Indy Soc
23、ket 组件( IdTCPClient 和 IdTCPServer )和 Delphi 原生的 TCPSocket 组件( ClientSocket 和 ServerSocket )。但 是, Borland 已宣称 ClientSocket 和 ServerSocket 组件即将被废弃,建议用相应的 Indy组件来代替。因此,笔者使用了 Indy 。本文在对 Indy 进行简要介绍的基础上, 创建了一组简单的 TCPSocket 数据传输应用来演示了 Indy 的使用方法。开放源代码的 Internet 组件集 Internet Direct (Indy ) Internet Direct
24、(Indy )是一组开放源 代码的 Internet 组件,涵盖了几乎所有流行的 Internet 协议。 Indy 用 Delphi 编写,被包含在Delphi 6,Kylix 1和C+ Builder 6及以上各个版本的 Borland开发环境中。Indy曾经叫做 WinShoes (双关于 WinSockWindows的Socket库),是由Chad乙Hower领导的一群开发者构建的,可以从 Indy 的站 上找到更多的信息并下载其新版本。到笔者撰写本文时 为止, Indy 的最新稳定版是 9.0.14 , Indy 10 也进入了 Beta 测试阶段。Delphi 7 中所带的是 In
25、dy 9 。在其的组件面板上,一共安装有 100多个 Indy 组件。使用这些组件你 可以开发基于各种协议的 TCP客户和服务器应用程序,并处理相关的编码和安全问题。你可以通过前缀 Id 来识别 Indy 组件。Indy 是阻塞式( Blocking )的当你使用 Winsock 开发网络应用程序时,从 Socket 中读取数据或者向 Socket 写入数据都是异步发生 的,这样就不会阻断程序中其它代码的执行。在收到数据时,Winsock 会向应用程序发送相应的消息。这种访问方式被称作非阻塞式连接,它要求你对事件作出响应,设置状态机,并通常还需要 一个等待循环。与通常的 Winsock 编程方
26、法不同的是, Indy 使用了阻塞式 Socket 调用方式。阻塞式访问更像是文件存取。当你读取数据,或是写入数据时,读取和写入函数将一直等到相应的操作完成后才返回。比如说,发起网络连接只需调用 Connect 方法并等待它返回,如果该方法执行成功,在结束时就 直接返回,如果未能成功执行,则会抛出相应的异常。同文件访问不同的是,Socket调用可能会需要更长的时间, 因为要读写的数据可能不会立即就能准备好 (在很大程度上依赖于网络带宽) 。阻塞式 Socket 并非恶魔( Evil )长期以来, 阻塞式 Socket 都遭到了毫无理由的攻击。 其实阻塞式 Socket 并非如通常所说的那样可怕
27、。 这还要从 Winsock 的发展说起。当 Socket 被从 Unix 移植到 Windows 时,一个严重的问题立即就出现了。 Unix 支持 fork ,客户程序和 服务器都能够 fork 新的进程,并启动这些进程,从而能够很方便地使用阻塞式 Socket 。而 Windows 3.x 既不支持 fork 也不支持多线程,当使用阻塞式 Socket 时,用户界面就会被“锁住”而无 法响应用户输入。为克服 Windows 3.x 的这一缺陷,微软在 Winsock 中加入了异步扩展,以使 Winsock 不会“锁住”应 用程序的主线程(也是唯一的线程) 。然而,这需要了一种完全不同的编程
28、方式。于是有些人为了掩饰这一弱点,就开始强烈地诽谤阻塞式 Socket 。当 Win32 出现的时候,它能够很好地支持线程。但是既成的观念已经很难更改,并且说出去的话也无 法收回,因此对阻塞式 Socket 的诽谤继续存在着。事实上,阻塞式 Socket 仍然是 Unix 实现 Socket 的唯一方式,并且它工作得很好。阻塞式 Socket 的优点归结起来,在 Windows 上使用阻塞式 Socket 开发应用程序具有如下优点:编程简单阻塞式 Socket 应用程序很容易编写。 所有的用户代码都写在同一个地方, 并且顺序执行。 容易向 Unix 移植由于 Unix 也使用阻塞式 Socke
29、t ,编写可移植的代码就变得比较容易。 Indy 就是利用 这一点来实现其多平台支持而又单一源代码的设计。很好地利用了线程技术阻塞式 Socket 是顺序执行的, 其固有的封装特性使得它能够很容易地使用 到线程中。阻塞式 Socket 的缺点事物都具有两面性, 阻塞式 Socket 也不例外。它的一个主要的缺点就是使客户程序的用户界面 “冻结” 当在程序的主线程中进行阻塞式 Socket 调用时,由于要等待 Socket 调用完成并返回,这段时间就不能处理用户界面消息,使得Update 、Repaint 以及其它消息得不到及时响应,从而导致用户界面被“冻结” 。使用 TIdAntiFreeze
30、 对抗“冻结”Indy 使用一个特殊的组件 TIdAntiFreeze 来透明地解决客户程序用户界面“冻结”的问题。TIdAntiFreeze 在 Indy 内部定时中断对栈的调用,并在中断期间调用Application.ProcessMessages方 法 处 理 消 息 , 而 外 部 的 Indy 调 用 继 续 保 存 阻 塞 状 态 , 就 好 像TIdAntiFreeze 对象不存在一样。你只要在程序中的任意地方添加一个 TIdAntiFreeze 对象,就能在客户程序中利用到阻塞式 Socket 的所有优点而避开它的一些显著缺点。Indy 使用了线程技术阻塞式 Socekt 通常
31、都采用线程技术, Indy 也是如此。从最底层开始, Indy 的设计都是线程化的。因此用 Indy 创建服务器和客户程序跟在 Unix 下十分相似,并且 Delphi 的快速开发环境和Indy 对 WinSock 的良好封装使得应用程序创建更加容易。Indy 服务器模型一个典型的 Unix 服务器有一个或多个监听进程, 它们不停地监听进入的客户连接请求。 对于每一个需 要服务的客户,都 fork 一个新进程来处理该客户的所有事务。这样一个进程只处理一个客户连接,编程就变得十分容易。Indy 服务器工作原理同 Unix 服务器十分类似, 只是 Windows 不像 Unix 那样支持 fork
32、 ,而是支持线程, 因此 Indy 服务器为每一个客户连接分配一个线程。图 1 显示了 Indy 服务器的工作原理。 Indy 服务器组件创建一个同应用程序主线程分离的监听线程来 监听客户连接请求,对于接受的每一个客户,都创建一个新的线程来为该客户提供服务,所有与这一客户相关的事务都由该线程来处理。使用组件 TIdThreadMgrPool , Indy 还支持线程池。上一页 1 2 3 4 下一页线程与 Indy 客户程序Indy 客户端组件并未使用线程。但是在一些高级的客户程序中,程序员可以在自定义的线程中使用Indy 客户端组件,以使用户界面更加友好。简单的 Indy 应用示例下面将创建
33、一个简单的 TCP客户程序和一个简单的 TCP服务器来演示Indy的基本使用方法。客户程序使用TCP协议同服务器连接,并向服务器发送用户所输入数据。服务器支持两条命令:DATA和QUIT。在DATA命令后跟随要发送的数据,并用空格将命令字DATA和数据分隔开表单布局建立一个项目组,添加一个客户程序项目和一个服务器项目。客户程序和服务器程序的表单布局如同2 和图 3 所示。客户程序表单上放置了 TIdTCPClient 组件,服务器程序表单上放置了TIdTCPServer 组件。为防止客户程序“冻结” ,还在其表单上放置 TIdAntiFreeze 组件。客户程序和服务器程序的表单上都放置有 T
34、ListBox 组件,用来显示通信记录。客户程序代码客户程序片断如代码列表 1 所示。代码列表 1procedure TFormMain.BtnConnectClick(Sender: TObject);beginIdTCPClient.Host := EdtHost.Text;IdTCPClient.Port := StrToInt(EdtPort.Text);LbLog.Items.Add(' 正在连接 ' + EdtHost.Text + '.');with IdTCPClient dobegintryConnect(5000);tryLbLog.Item
35、s.Add(ReadLn();BtnConnect.Enabled := False;BtnSend.Enabled := True;BtnDisconnect.Enabled := True; exceptLbLog.Items.Add(' 远程主机无响应! ');IdTCPClient.Disconnect();end;/end try exceptLbLog.Items.Add(' 无法建立到 ' + EdtHost.Text + '的连接! ');end;/end tryend;/end withend;procedure TFormMa
36、in.BtnSendClick(Sender: TObject); beginLbLog.Items.Add('DATA ' + EdtData.Text);with IdTCPClient dobegintryWriteLn('DATA ' + EdtData.Text);LbLog.Items.Add(ReadLn()exceptLbLog.Items.Add(' 发送数据失败! ');IdTCPClient.Disconnect();LbLog.Items.Add(' 同主机 ' + EdtHost.Text + '
37、 的连接已断开! ');BtnConnect.Enabled := True;BtnSend.Enabled := False;BtnDisconnect.Enabled := False;end;/end tryend;/end withend;procedure TFormMain.BtnDisconnectClick(Sender: TObject);varReceived: string;beginLbLog.Items.Add('QUIT');tryIdTCPClient.WriteLn('QUIT');finallyIdTCPClient.D
38、isconnect();LbLog.Items.Add(' 同主机 ' + EdtHost.Text + ' 的连接已断开! ');BtnConnect.Enabled := True;BtnSend.Enabled := False;BtnDisconnect.Enabled := False;end;/end tryend;在“连接”按钮事件响应过程中,首先根据用户输入设置 IdTCPClient 的主机和端口,并调用 IdTCPClient 的 Connect 方法向服务器发出连接请求。然后调用ReadLn 方法读取服务器应答数 据。在“发送”按钮事件响应
39、过程中,调用WriteLn方法写DATA命令,向服务器发送数据在“断开”按钮事件响应过程中,向服务器发送QUIT命令,并调用Disconnect方法断开连接。程序中还包含有通信信息记录和异常处理的代码。服务器程序代码服务器程序片断如代码列表 2 所示。代码列表 2procedure TFormMain.BtnStartClick(Sender: TObject); beginIdTCPServer.DefaultPort := StrToInt(EdtPort.Text);IdTCPServer.Active := True;BtnStart.Enabled := False;BtnStop.
40、Enabled := True;LbLog.Items.Add(' 服务器已成功启动! ');end;procedure TFormMain.BtnStopClick(Sender: TObject); beginIdTCPServer.Active := False;BtnStart.Enabled := True;BtnStop.Enabled := False;LbLog.Items.Add(' 服务器已成功停止! ');end;procedure TFormMain.IdTCPServerConnect(AThread: TIdPeerThread);
41、beginLbLog.Items.Add(' 来自主机 '+ + ' 的连接请求已被接纳! ');AThread.Connection.WriteLn('100:欢迎连接到简单 TCP服务器!);end;procedure TFormMain.IdTCPServerExecute(AThread: TIdPeerThread);varsCommand: string;beginwith AThread.Connection dobeginsCommand := ReadLn();FLogEntry := sCommand + ' 来自于主机
42、39;+ AThread.Connection.Socket.Binding.PeerIP; AThread.Synchronize(AddLogEntry);if AnsiStartsText('DATA ', sCommand) thenbeginFReceived := RightStr(sCommand, Length(sCommand)-5);WriteLn('200: 数据接收成功! ');AThread.Synchronize(DisplayData);endelse if SameText(sCommand, 'QUIT') th
43、en beginFLogEntry := ' 断开同主机 '+ + ' 的连接! 'AThread.Synchronize(AddLogEntry);Disconnect;endelse beginWriteLn('500: 无法识别的命令! ');FLogEntry := ' 无法识别命令: ' + sCommand;AThread.Synchronize(AddLogEntry);end;/endifend;end;procedure TFormMain.DisplayData();beginEdtData.Text := F
44、Received;end;procedure TFormMain.AddLogEntry();beginLbLog.Items.Add(FLogEntry);end;“启动”按钮设置 IdTCPServer 的 Active 属性为 True 来启动服务器, “停止”按钮设置 Active 属性 为 False 来关闭服务器。IdTCPServerConnect 方法作为 IdTCPServer 的 OnCorrect 事件响应过程,向客户端发送欢迎信息。 OnCorrect 事件在一个客户连接请求被接受时发生,为该连接创建的线程 AThread 被作为参数传递给 IdTCPServerCon
45、nect 方法。IdTCPServerExecute 方 法 是 IdTCPServer 的 OnExecute 事 件 响 应 过 程 。 OnExecute 事 件 在 TIdPeerThread 对象试图执行其 Run 方法时发生。 OnExecute 事件与通常的事件有所不同,其响应过 程是在某个线程上下文中执行的,参数 AThread 就是调用它的线程。这一点很重要,它意味着可能有多个 OnExecute 事件响应过程被同时执行。在连接被断开或中断前,OnExecute 事件响应过程会被反复执行。在IdTCPServerExecute方法中,首先读入一条指令,然后对指令进行判别。如果
46、是DATA指令,就解出数据并显示它。如果收到的是QUIT指令,则断开连接。需要特别指出的是,由于IdTCPServerExecute 方法在某一线程上下文中执行,因此显示数据和添加事件记录都是将相应的方法传递给 Synchronize 调用来完成的。运行程序运行客户端和服务器程序,按如下流程进行操作:1. 按服务器程序的“启动”按钮启动服务器;2. 按客户程序的“连接”按钮,建立同服务器的连接;3. 在客户程序的待发送数据编辑框中输入“ Hello, Indy! ”,并按“发送”按钮发送数据;4. 按客户程序的“断开”按钮,断开同服务器的连接;5. 按服务器程序的“停止”按钮停止服务器。用 S
47、ocket 接收和转换数字和字符串数据 【大 中 小】【打印】【加入收藏】【关闭】浏览字号 : 日期:2005-06-13 人气: 60 出处: 作者: 7nightlove很多时候远程系统在执行并发任务的时候,会把它接收到数据的长度以数字的形式发送出去。但用 socket 发送和接收数字型数据的时候 , 要考虑到一个问题:要根据网络另一端机器的类型转换数据。尤其 需要知道怎样把要发送的数据格式(网络格式)从本地机器的格式(主机格式)转换成为行业标准格式。使 用 IPAddress.NetworkToHostOrder 可 以 把 数 据 从 网 络 规 则 转 换 为 主 机 格 式 , 下
48、 面 的ReceiveHeader 函数说明了它的用法, ReceiveHeader 函数实现过程如下:1 用 Socket.Receive 从远程机器接收数据。2 验证接收到的字节数是 4。3 Socket.Receive 返回一个字节型数组, BitConvert.ToInt32 把它转换成数字型数值。4 最后, IPAddress.NetworkToHostOrder 把长数值转换为主机格式。public int ReceiveHeader(Socket socket)int dataSize = -1; / errorbyte buffer = new byte4;int bytesR
49、ead = socket.Receive(buffer, 4,System.Net.Sockets.SocketFlags.None);if (4 = bytesRead)dataSize = BitConverter.ToInt32(buffer, 0);dataSize = IPAddress.NetworkToHostOrder(dataSize);else / error conditionreturn dataSize;下面再来看一下怎样用多线程读取的方法为每个字符串都建立连接, 从远程机器接收字符串型数据。 在这种情况下,要把字 节型数据转换成 String 型对象。你可以根 据需
50、要用 ASCIIEncoding 或 UnicodeEncoding 类进行转换。 ReceiveDetail 函数按以下步骤实现 (此函数必须在 ReceiveHeader 后调用, 因为 datasize 的值是从 ReceiveHeader 中得到的。)1 在 while 循环中调用 Socket.Receive ,直到无返回值为止。数据被读入一个字节型数组。2 建立一个 ASCIIEncoding 对象。3 调用 ASCIIEncoding.GetString 把字节型数组转换成 String 对象,然后把它和先前读入的数据连接。public string ReceiveDetail(
51、Socket socket, byte buffer,int dataSize)string response = ""int bytesReceived = 0;int totalBytesReceived = 0;while (0 < (bytesReceived =socket.Receive(buffer, (dataSize - totalBytesReceived), SocketFlags.None)totalBytesReceived += bytesReceived;ASCIIEncoding encoding = new ASCIIEncoding
52、(); response += encoding.GetString(buffer, 0, bytesReceived);return response;在 Delphi 7 中用 Indy 开发 Socket 应用程序2003-11-26 14:13:55虚度笔者在前一段的工作中, 需要开发一套简单的网络数据传输程序。由于平时常用 Delphi 做点开发, 故此 次也不例外。 Delphi 7 中带有两套 TCP Socket 组件: Indy Socket 组件( IdTCPClient 和 IdTCPServer )和 Delphi 原生的 TCPSocket 组件(Clientsock
53、et 和 ServerSocket )。但是,Borland 已宣称 ClientSocket 和 ServerSocket 组件即将被废弃,建议用相应的 Indy 组件来代替。 因此, 笔者使用 了 Indy 。本文在对 Indy 进行简要介绍的基础上, 创建了一组简单的 TCPSocket 数据传输应用来演示了 Indy 的使用方法。开放源代码的 Internet 组件集 Internet Direct (Indy )Internet Direct (Indy )是一组开放源代码的Internet 组件,涵盖了几乎所有流行的Internet 协议。Indy 用 Delphi 编写,被包含在
54、 Delphi 6 , Kylix 1 和 C+ Builder 6 及以上各个版本的 Borland 开发环境中。 Indy曾经叫做 WinShoes (双关于 WinSockWindows的Socket库),是由Chad乙Hower领导的一群开发者构建的,可以从 Indy 的站点 上找到更多的信息并下载其新版本。到笔者撰写 本文时为止, Indy 的最新稳定版是 9.0.14 , Indy 10 也进入了 Beta 测试阶段。Delphi 7 中所带的是 Indy 9 。在其的组件面板上,一共安装有 100多个 Indy 组件。使用这些组件你可以 开发基于各种协议的TCP客户和服务器应用程
55、序,并处理相关的编码和安全问题。你可以通过前缀Id来识 别 Indy 组件。Indy 是阻塞式( Blocking )的当你使用 Winsock 开发网络应用程序时,从 Socket 中读取数据或者向 Socket 写入数据都是异步发生的, 这样就不会阻断程序中其它代码的执行。在收到数据时,Winsock 会向应用程序发送相应的消息。这种访问方式被称作非阻塞式连接,它要求你对事件作出响应,设置状态机,并通常还需要一个等待循环。与通常的 Winsock 编程方法不同的是, Indy 使用了阻塞式 Socket 调用方式。阻塞式访问更像是文件存取。 当你读取数据,或是写入数据时,读取和写入函数将一
56、直等到相应的操作完成后才返回。比如说,发起网 络连接只需调用 Connect 方法并等待它返回,如果该方法执行成功,在结束时就直接返回,如果未能成功 执行,则会抛出相应的异常。同文件访问不同的是, Socket 调用可能会需要更长的时间,因为要读写的数 据可能不会立即就能准备好(在很大程度上依赖于网络带宽) 。阻塞式 Socket 并非恶魔( Evil )长期以来,阻塞式 Socket 都遭到了毫无理由的攻击。其实阻塞式 Socket 并非如通常所说的那样可怕。这 还要从 Winsock 的发展说起。当 Socket 被从 Unix 移植到 Windows 时,一个严重的问题立即就出现了。 U
57、nix 支持 fork ,客户程序和服务 器都能够 fork 新的进程,并启动这些进程,从而能够很方便地使用阻塞式Socket 。而 Windows 3.x 既不支持 fork 也不支持多线程,当使用阻塞式 Socket 时,用户界面就会被“锁住”而无法响应用户输入。为克服 Windows 3.x 的这一缺陷,微软在 Winsock 中加入了异步扩展,以使 Winsock 不会“锁住”应用程 序的主线程(也是唯一的线程) 。然而,这需要了一种完全不同的编程方式。 于是有些人为了掩饰这一弱点, 就开始强烈地诽谤阻塞式 Socket 。当 Win32 出现的时候,它能够很好地支持线程。但是既成的观念已经很难更改,并且说出去的话也无法收 回,因此对阻塞式 Socket 的诽谤继续存在着。事实上,阻塞式 Socket 仍然是 Unix 实现 Socke
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024-2025版新教材高中化学 第2章 第3节 第1课时 认识氧化还原反应教学设计 鲁科版必修第一册
- 18 威尼斯的小艇 教学设计-2024-2025学年统编版语文五年级下册
- 《第2课 电话家族 2 电话魅力大》(教学设计)-2023-2024学年五年级下册综合实践活动安徽大学版
- 2023三年级语文上册 第三单元 习作:我来编童话配套教学设计 新人教版
- 泪腺炎诊疗规范
- 13 《湖心亭看雪》教学设计2024-2025学年九年级上册语文同步备课(统编版)
- 2 小小的船 (教学设计)2024-2025学年统编版一年级上册语文
- 2023八年级数学上册 第三章 位置与坐标3 轴对称与坐标变化教学设计 (新版)北师大版
- 泌尿常规护理操作流程
- 15番茄与番茄酱(教案)一年级下册科学青岛版
- 学校供水管理制度
- 2025年人教版高考历史总复习高中历史必修二专题知识点梳理总结
- 部编人教版语文小学六年级下册第四单元主讲教材解读(集体备课)
- (完整文本版)新概念英语第一册单词表默写版1-144
- 籍贯对照表完整版
- 火力发电企业作业活动风险分级管控清单(参考)
- 排油烟设施清洗技术规程
- 北京一心关爱慈善护理院项目说明书
- AD域部署方案完整版
- EN779-2012一般通风过滤器——过滤性能测定(中文版)
- 初一数学趣味竞赛试题
评论
0/150
提交评论