VBGood网站全文搜索 Google

搜索VBGood全站网页(全文搜索)
首页 - 经验之谈 - 用VB编制Tcp/IP程序
发表评论(0)作者:不详, 平台:VB6.0+Win98, 阅读:11475, 日期:2002-01-23
用VB编制Tcp/IP程序


--------------------------------------------------------------------------------

作者:尹华成   
          
                                          
     
     随着Internet 爆炸式的发展及Windows用户不断地增多,人们迫切地需要一种在Windows下开发TCP/IP应用程序标准,由包括微软公司在内的众多计算机厂家,经共同努力,已经制订出了这一标准,称之为Windows Sockets API(application Program interface)。这使得不同厂家开发的应用程序能够做到相互兼容。?
     
     一、TCP/IP编译简介:?
     当两台计算机通过网络要进行信息交换时,需要具备两个条件:一是物理配件,这包括网卡及连接网卡用的网线,二是需要一组通讯参数的说明,即协议。目前最广泛使用的协议是TCP/IP协议。?
     
     当一个主机使用IP协议发送数据时,数据被分为数据包.每个数据包由其包头及数据组成,包头包含对方目的地址。这就象使用信封发信一样,信封上含有收方的地址,但有时发出的信也会丢掉,这种发送称为不可靠的传输,而我们需要的是可靠的传输,这便产生了TCP协议。?
     
     TCP是一种面向连接的协议,即:两个程序在进行数据交换之前,他们必须先建立起连接,一个程序作为客户方(client)发出连接请求,另一个程序作为服务方(server)监听,并响应其连接请求,一旦连接建立好,双方便均可收发信息,直到连接断开。TCP协议使得开发人员不需要去编写如何处理数据包丢失的过程,而专心于应用程序本身的开发。
     
     为了同其他计算机进行通信,还需要知道本机及目的机的IP地址,有时为方便记忆我们将32位的IP地址用主机名来代替,主机名间用"·"分隔,我们称之为域,域是一种树形结构。如:? 最上一层为政府、商业公司、教育机构、internet服务商等组织,一个完整的域名是由主机及其所有的父名组成(用注释:·注释:分隔),例如mars的完整域名为mars·olgmpus·com,其表达的含意为mars是olgmpus域名的一部分,而olgmpus又是com的一部分。IP地址到主机名的转换有两种方法,一是使用本地的主机命名表文件,这个文件通常称为hosts文件,表中列出了IP地址及主机名的对应关系;二是使用命名服务器(DNS),它是一台主机(或一个应用程序),可以将一主机名转换为其IP地址。?
           
     此外,除了双方的IP地址以外,还需要知道对方的服务端口号(Service Port),它是一个16位的标识,每一Service Port同一应用程序相对应,这些对应关系往往存在于名为Service的一个文件中,一些常用的服务及对应的
     Service Port如下:?
     
     Service                               Servicse Port?
     FTP                                   21?
     Telnet                                23?
     SMTP                                  25?
     DNS                                   53?
     TFTP                                  69?
     SNMP                                  161?
     TCP                                   6?
     UDP                                   17?
     
     有了以上各信息,两应用程序在进行通讯时,先建立一个Socket(或称为通讯端点),建立了Socket本身并不能进行信息交换,你还必须建立Socket的连接,Socket的地址由三部分组成:协议、IP地址、Service Port号。其协议标识着下一层所使用何种协议,在我们以下的例子中就是指IP协议。?
        
     在两个应用程序进行通讯时,客户方建立一个Socket并试图同服务方建立连接,服务方也建立一个Socket等待客户方发来的连接请求,当收到一个申请后,双方便形成一条虚电路(即两个程序之间的一条逻辑通讯链路)。在此强调一下:当服务方收到连接请求后,服务方建立一新的Socket,用此新的Socket同对方建立连接,原来的Socket保持不变,可继续等待其它连接请求,当服务方不再希望收到其它连接时,它将最早的Socket关闭。?
         
     在建立一个TCP通讯程序时,服务方的程序应完成以下五个步骤:?
     1、建立一个Socket?
     2、监听从客户方发来的连接请求?
     3、接受客户方的连接?
     4、开始收、发信息?
     5、关闭Socket,终结会话?
     
     在客户方应完成以下五个步骤:?
     1、建立一个Socket?
     2、指定服务方IP地址及Service Port?
     3、同服务方建立连接?
     4、开始收、发信息?
     5、关闭Socket,终结会话?
     
     由上可以看出服务方和客户方的第二步和第三步是不同的,另外,在开发应用程序时,你可能会遇到阻塞式和非阻塞式Socket。例如:当你从Socket读数据时,如果远方主机还未将数据传来,你就读不到数据,这会引发两种情况:一是程序一直等待,直到数据到达;二是程序立即返回并标识一个读错误。前者我们称之为阻塞式Socket,后者为非阻塞式Socket,在非阻塞式的情况下,程序开发者应当做出适当的处理。一般有两种处理方法:第一种为轮询法,即程序周期的去读Socket;第二种是较好的一种方法,异步通知法,即当Socket发生事件时,能够通知应用程序,如:Socket收到远方主机发来的数据时,Socket会产生一个"读事件",应用程序便可从Socket中读出数据了。?
     
     二、TCP/IP编程实例?
     1.客户方软件的编制:?
     
     下面的例子假设读者对VB编程有一定的了解,其工作流程是:客户方发出的一串信息到服务方,服务方收到后将收到的信息全部传回来。?
         
     首先用VB创建一个带有三个标记、三个文本控件、一个控制按纽及一个SocketWrench控件,当使用时,用户在Text1中输入远端主机IP的地址或主机名,将要发送的信息输入到Text2中,服务方返回的信息便在Text3中显示。Text2及Text3的Enable属性在初始时设为False。程序如下:?
     
     Sub Form Load()?
     Socket1.AddressFamily=AF INET?
     Socket1.Protoco1=IPPROTO IP?
     Socket1.Type=SOCK STREAM?
     Socket1.Binary=False?
     Socket1.BufferSize=1024?
     Socket1.Blocking=False?
     End Sub?
        
     当点击Connect后,便可建立同远方主机的连接,其过程如下:?
     Sub Command Click()?
     Socket1.HostName=Trim$(Text1.Text)?
     Socket1.RemotePort=IPPORT ECHO?
     Socket1.Action=SOCKET CONNECT?
     End Sub?
     
     在初始化的过程中,我们已将其Socket定为非阻塞式的(Socket1.Blocking=Fasle),因此它不必等待连接建立完,而是直接返回,并等待connect事件,当此事件发生后对其进行响应,程序如下:?
     
     Sub Socket1 Connect()?
     Text2.Enabled=True?
     Text3.Enabled=True?
     End Sub?
     此时,Text2,Text3便可进行数据的输入/输出了。?下一步的程序为真正的收发过程,在Text2控件中加入KeyPress事件:?
     Sub Text2 KeyPress(KeyAscii As Integet)?
     If KeyAscii=13 Then?
     Socket1.SendLen=Len(Text2.Text)?
     Socket1.SendData=Text2.Text?
     KeyAscii=0:Text2.Text=""?
     End If?
     End Sub?
         
     当按下Enter时(KeyPress=13)数据便会发往远程主机发送数据,远程主机接到数据并传回,并在客户方产生一个读事件,处理读事件的过程如下:?
     Sub Socket1 Read(DataLength As Integer,IsUrgent As Integer)?
     Socket1.RecvLen=DataLength?
     Text3.Text=Socket1.RecvData?
     End Sub?
     
     当终结此连接时,在Form unload事件处加如下过程:?
     Sub Form Unload(Cancel As Integer)?
     If Socket1.Connected Then Socket1.Action=SOCKET CLOSE?
     End If?
     End Sub?
     
     到此,一个较为完整的VB程序已经完成,但是如果输入IP的地址或主机名不正确时,还需要编一个处理程序,这已超过本篇介绍的目的,在此就不做介绍了.?
     
     2、服务方软件的编制?
     服务方软件的第一件事情就是监听是否有连接的请求,当SocketWrench收到连接请求时,就会产生一个Accept事件,这时有两种处理方法:一是将Action属性设置为SOCKET ACCEPT;二是对Accept属性进行设置。前者较为简单但有局限性,因为它将结束监听其它的连接请求,只能同第一个客户建立连接。后者较为灵活但较为复杂,其方法是对Accept设置属性。然而,正在监听的控件不能设置Accept属性,必须利用闲置的Socket来对其进行设置,因此就需要一个控件组来处理多个连接。为方便起见,我们还利用前面使用的Form来编制服务方的应用。首先是再加上一个SocketWrench控件,并使之成为控件组。开始时此控件组中只有一个控件。称为Socket2(0),这个控件组用来监听连接请求,同客户方一样,也需先对其进行初始化:?
     
     Sub Form Load()?
     Socket1.AddressFamily=AF INET?
     Socket1.Proyocol=IPPROTO IP?
     Socket1.Type=SOCK STREAM?
     Socket1.Binary=False?
     Socket1.BufferSize=1024?
     Socket1.Blocking=False?
     Socket2(0) .Addr essFamily=AF INET?
     Socket2(0) .Proyocol=IPPROTO IP?
     Socket2(0) .Type=SOCK STREAM?
     Socket2(0) .Blocking=False?
     Socket2(0) .Localport=IPPORT ECHO?
     Socket2(0) .Action=SOCKET LISTEN?
     LastSocket=0?
     End Sub?
     
     其中local port指明了当接到对方数据时,将其全部传回的一个TCP系统应用。当服务器收到连接请求时,就会出现一个Accept事件,相应的处理过程如下:?
     
     Sub Socket2 Accept(Index As Integer,Sockerid As Integer)?
     Dim I As Integer?
     For I=1 To LastSocket?
     If Not Socket2(I).Connected Then Exit For?
     Next I?
     If I>LastSocket Then?
     LastSocket=LastSocket+1:I=LastSocket?
     Load Socket2(I)?
     End If?
     Socket2(I).AddressFamily=AF INET?
     Socket2(I).Protocol=IPPROTO IP?
     Socket2(I).Type=SOCK STREAM?
     Socket2(I).Binary=True?
     Socket2(I).BufferSize=1024?
     Socket2(I).Blocking=False?
     Socket2(I).Accept=SocketId?
     End Sub?
     
     以上程序收到一个连接时,产生一个新的SocketWrench控件,在对其进行初始化之后,便可同客户方通讯了.原Socket继续监听是否有新的连接请求。?服务方收到数据后,将全部数据再传回客户方,其处理过程如下;?
     
     Sub Socket2 Read(Index As Integer,DataLength As Integer,IsUrgent As Integer)?
     Socket2(Index).RecvLen=DataLength?
     Socket2(Index).SendLen=DataLength
     Socket2(Index).SendData=Socket2(Index).RecvData?
     End Sub?
     
     当客户方关闭连接,服务方也关闭相应Socket的控制,过程如下:?
     Sub Socket2 Close(Index As Integer)?
     Socket2(Index).Action=SOCKET CLOSE?
     End Sub?
     
     断开所有连接的程序如下:?
     Sub From Unload(Cancel As Integer)?
     Dim I As Integer?
     If Socket1.Connected Then Socket1.Action=SOCKET CLOSE?
     If Socket2(0).Listening Then Socket2(0).Action=SOCKET CLOSE?
     For I=1 To LastSocket?
     If Socket2(0).Connected Then Socket2(0).Action=SOCKET CLOSE?
     Next I?
     End?
     End Sub?
     到这里,我们就可以使用这个程序利用TCP/IP协议进行信息交换了。?