[VB.NET]Winsock控件(广域网编程)

时间:2021-06-27 14:02:18
  • Winsock   控件   
  •                             
  •     
  •   Winsock   控件对用户来说是不可见的,它提供了访问   TCP   和   UDP   网络服务的方便途径。Microsoft   Access、Visual   Basic、Visual   C++   或   Visual   FoxPro   的开发人员都可使用它。为编写客户或服务器应用程序,不必了解   TCP   的细节或调用低级的   Winsock   APIs。通过设置控件的属性并调用其方法就可轻易连接到一台远程机器上去,并且还可双向交换数据。   
  •     
  •   TCP   基础   
  •     
  •   数据传输协议允许创建和维护与远程计算机的连接。连接两台计算机就可彼此进行数据传输。   
  •     
  •   如果创建客户应用程序,就必须知道服务器计算机名或者   IP   地址(RemoteHost   属性),还要知道进行“侦听”的端口(RemotePort   属性),然后调用   Connect   方法。   
  •     
  •   如果创建服务器应用程序,就应设置一个收听端口(LocalPort   属性)并调用   Listen   方法。当客户计算机需要连接时就会发生   ConnectionRequest   事件。为了完成连接,可调用   ConnectionRequest   事件内的   Accept   方法。   
  •     
  •   建立连接后,任何一方计算机都可以收发数据。为了发送数据,可调用   SendData   方法。当接收数据时会发生   DataArrival   事件。调用   DataArrival   事件内的   GetData   方法就可获取数据。   
  •     
  •   UDP   基础   
  •     
  •   用户数据文报协议   (UDP)   是一个无连接协议。跟   TCP   的操作不同,计算机并不建立连接。另外   UDP   应用程序可以是客户机,也可以是服务器。   
  •     
  •   为了传输数据,首先要设置客户计算机的   LocalPort   属性。然后,服务器计算机只需将   RemoteHost   设置为客户计算机的   Internet   地址,并将   RemotePort   属性设置为跟客户计算机的   LocalPort   属性相同的端口,并调用   SendData   方法来着手发送信息。于是,客户计算机使用   DataArrival   事件内的   GetData   方法来获取已发送的信息。
  • 使用   Winsock   控件   
  •     
  •   利用   WinSock   控件可以与远程计算机建立连接,并通过用户数据文报协议   (UDP)或者传输控制协议   (TCP)进行数据交换。这两种协议都可以用来创建客户与服务器应用程序。与   Timer   控件类似,WinSock   控件在运行时是不可见的。   
  •     
  •   可能的用途   
  •   创建收集用户信息的客户端应用程序,并将收集的信息发送到某*服务器。   
  •     
  •     
  •   创建一个服务器应用程序,作为多个用户的数据的汇入点。   
  •     
  •     
  •   创建“聊天”应用程序。     
  •   选择通讯协议   
  •   在使用   WinSock   控件时,首先需要考虑使用什么协议。可以使用的协议包括   TCP   和   UDP。两种协议之间的重要区别在于它们的连接状态:     
  •     
  •   TCP   协议控件是基于连接的协议,可以将它同电话系统相比。在开始数据传输之前,用户必须先建立连接。   
  •     
  •     
  •   UDP   协议是一种无连接协议,两台计算机之间的传输类似于传递邮件:消息从一台计算机发送到另一台计算机,但是两者之间没有明确的连接。另外,单次传输的最大数据量取决于具体的网络。     
  •   到底选择哪一种协议通常是由需要创建的应用程序决定的。下面的几个问题将有助于选择适宜的协议:     
  •     
  •   在收发数据的时候,应用程序是否需要得到客户端或者服务器的确认信息?如果需要,使用   TCP   协议,在收发数据之前先建立明确的连接。   
  •     
  •     
  •   数据量是否特别大(例如图象与声音文件)?在连接建立之后,TCP   协议将维护连接并确保数据的完整性。不过,这种连接需要更多的计算资源,因而是比较“昂贵”的。   
  •     
  •     
  •   数据发送是间歇的,还是在一个会话内?例如,如果应用程序在某个任务完成的时候需要通知某个计算机,UDP   协议是更适宜的。UDP   协议适合发送少量的数据。     
  •   协议的设置   
  •   在设计时,可以按如下方式设置应用程序使用的协议:在“属性”窗口中单击“协议”,然后选择   sckTCPProtocol   或者   sckUDPProtocol。也可以使用程序代码来设置   Protocol   属性,如下所示:   
  •     
  •   Winsock1.Protocol   =   sckTCPProtocol   
  •     
  •   确定计算机的名称   
  •   在与远程计算机相连接的时候,需要知道它的   IP   地址或者它的“好听的名字”。IP   地址是一串数字,每三个数字为一组,中间用点隔开(形如   xxx.xxx.xxx.xxx)。通常,最易记住的是计算机的“好听的名字”。   
  •     
  •   要确定计算机的名字,请按照以下步骤执行:     
  •     
  •   在计算机的“任务栏”上,单击“启动”。   
  •     
  •     
  •   在“设置”项中,单击“控制面板”。   
  •     
  •     
  •   双击“网络”图标。   
  •     
  •     
  •   单击“标识”选项卡。   
  •     
  •     
  •   在“计算机名称”框中可以找到计算机的名称。     
  •   上面找到的计算机名称可以作为   RemoteHost   属性的值。   
  •     
  •   TCP   连接初步   
  •   如果应用程序要使用   TCP   协议,那么首先必须决定应用程序是服务器还是客户端。如果要创建一个服务器端,那么应用程序需要“监听”指定的端口。当客户端提出连接请求时,服务器端能够接受请求并建立连接。在连接建立之后,客户端与服务器端可以*地互相通讯。   
  •     
  •   下列步骤创建一个非常简单的服务器:   
  •     
  •   要创建一个   TCP   服务器,请按照以下步骤执行:     
  •     
  •   创建新的   Standard   EXE   工程。   
  •     
  •     
  •   将缺省窗体的名称改为   frmServer。   
  •     
  •     
  •   将窗体的标题改为“TCP   服务器”。   
  •     
  •     
  •   在窗体中放入一个   Winsock   控件,并将它的名字改为   tcpServer。   
  •     
  •     
  •   在窗体上添加两个   TextBox   控件。将第一个命名为   txtSendData,第二个为   txtOutput。   
  •     
  •     
  •   为窗体添加如下的代码。     
  •   Private   Sub   Form_Load()   
  •   '将   LocalPort   属性设置为一个整数。   
  •   '然后调用   Listen   方法。   
  •   tcpServer.LocalPort   =   1001   
  •   tcpServer.Listen     
  •   frmClient.Show   '显示客户端的窗体。   
  •   End   Sub   
  •     
  •   Private   Sub   tcpServer_ConnectionRequest   _   
  •   (ByVal   requestID   As   Long)   
  •   '检查控件的   State   属性是否为关闭的。   
  •   '如果不是,   
  •   '在接受新的连接之前先关闭此连接。   
  •   If   tcpServer.State   <>   sckClosed   Then   _   
  •   tcpServer.Close   
  •   '接受具有   requestID   参数的   
  •   '连接。   
  •   tcpServer.Accept   requestID   
  •   End   Sub   
  •     
  •   Private   Sub   txtSendData_Change()   
  •   '名为   txtSendData   的   TextBox   控件中   
  •   '包含了要发送的数据。当用户往文本框中   
  •   '键入数据时,使用   SendData   方法   
  •   '发送输入的字符串。   
  •   tcpServer.SendData   txtSendData.Text   
  •   End   Sub   
  •     
  •   Private   Sub   tcpServer_DataArrival   _   
  •   (ByVal   bytesTotal   As   Long)   
  •   '为进入的数据声明一个变量。   
  •   '调用   GetData   方法,并将数据赋予名为   txtOutput     
  •   '的   TextBox   的   Text   属性。   
  •   Dim   strData   As   String   
  •   tcpServer.GetData   strData   
  •   txtOutput.Text   =   strData   
  •   End   Sub   
  • 上面的步骤创建了一个简单的服务器应用程序。为了使它能够工作,还必须为它创建一个客户端的应用程序。   
  •     
  •   要创建   TCP   客户端,请按照以下步骤执行:     
  •     
  •   在工程中添加一个新的窗体,将其命名为   frmClient。   
  •     
  •     
  •   将窗体的标题改为“TCP   Client”。   
  •     
  •     
  •   在窗体中添加一个   Winsock   控件,并将其命名为   tcpClient。   
  •     
  •     
  •   在   frmClient   中添加两个   TextBox   控件。将第一个命名为   txtSend,第二个为   txtOutput。   
  •     
  •     
  •   在窗体上放一个   CommandButton   控件,并将其命名为   cmdConnect。   
  •     
  •     
  •   将   CommandButton   控件的标题改为   Connect。   
  •     
  •     
  •   在窗体中添加如下的代码。     
  •   重点       必须将   RemoteHost   属性值修改为您的计算机的名字。   
  •     
  •   Private   Sub   Form_Load()   
  •         'Winsock   控件的名字为   tcpClient。   
  •         '注意:要指定远程主机,可以使用   
  •         '   IP   地址(例如:"121.111.1.1"),也可以使用   
  •         '计算机的“好听的名字”如下所示。   
  •         tcpClient.RemoteHost   =   "RemoteComputerName"   
  •         tcpClient.RemotePort   =   1001   
  •   End   Sub   
  •     
  •   Private   Sub   cmdConnect_Click()   
  •         '调用   Connect   方法,初始化连接。   
  •         tcpClient.Connect   
  •   End   Sub   
  •     
  •   Private   Sub   txtSendData_Change()   
  •         tcpClient.SendData   txtSend.Text   
  •   End   Sub   
  •     
  •   Private   Sub   tcpClient_DataArrival   _   
  •   (ByVal   bytesTotal   As   Long)   
  •         Dim   strData   As   String   
  •         tcpClient.GetData   strData   
  •         txtOutput.Text   =   strData   
  •   End   Sub   
  •     
  •   上面的代码创建了一个简单的客户/服务器模式的应用程序。我们可以将两者都运行起来:运行工程,然后单击“连接”。在两个窗体之一的   txtSendData   文本框中键入文本,可以看到同样的文字将出现在另一个窗体的   txtOutput   文本框中。   
  •     
  •   接受多个连接请求   
  •   上面设计的基本服务器只能接受一个连接请求。通过创建控件数组,使用一个控件也可以同时接受多个连接请求。利用这种方法,不需要关闭连接,而只需创建新的控件实例(通过设置其索引属性),然后在新的实例上调用   Accept   方法。   
  •     
  •   下面的代码假定名为   sckServer   的窗体上有一个   Winsock   控件,它的   Index   属性被设置为   0;因此控件是控件数组的一部分。在声明部分,声明了一个模块级的变量   intMax。在窗体的   Load   事件中,intMax   被设置为   0,数组中第一个控件的   LocalPort   属性被设置为   1001。然后调用控件的   Listen   方法,使之成为“监听”控件。在连接请求到达时,代码将检测   Index   是否为   0(“监听”控件的值)。如果为   0,监听控件将增加   intMax   的值,并使用该号码来创建新的控件实例。然后,使用新的控件实例接受连接请求。   
  •     
  •   Private   intMax   As   Long   
  •     
  •   Private   Sub   Form_Load()   
  •         intMax   =   0   
  •         sckServer(0).LocalPort   =   1001   
  •         sckServer(0).Listen   
  •   End   Sub   
  •     
  •   Private   Sub   sckServer_ConnectionRequest   _   
  •   (Index   As   Integer,   ByVal   requestID   As   Long)   
  •         If   Index   =   0   Then   
  •               intMax   =   intMax   +   1   
  •               Load   sckServer(intMax)   
  •               sckServer(intMax).LocalPort   =   0   
  •               sckServer(intMax).Accept   requestID   
  •               Load   txtData(intMax)   
  •         End   If   
  •   End   Sub   
  •     
  •   UDP   初步   
  •   创建   UDP   应用程序比创建   TCP   应用程序还要简单,因为   UDP   协议不需要显式的连接。在上面的   TCP   应用程序中,一个   Winsock   控件必须显式地进行“监听”,另一个必须使用   Connect   方法初始化连接。   
  •     
  •   UDP   协议不需要显式的连接。要在两个控件中间发送数据,需要完成以下的三步(在连接的双方):     
  •     
  •   将   RemoteHost   属性设置为另一台计算机的名称。   
  •     
  •     
  •   将   RemotePort   属性设置为第二个控件的   LocalPort   属性。   
  •     
  •     
  •   调用   Bind   方法,指定使用的   LocalPort。(下面将详细地讨论该方法。)     
  •   因为两台计算机的地位可以看成“平等的”,这种应用程序也被称为点到点的。为了具体说明这个问题,下面将创建一个“聊天”应用程序,两个人可以通过它进行实时的交谈。   
  •     
  •   要创建一个   UDP   伙伴,请按照以下步骤执行:     
  •     
  •   创建一个新的   Standard   EXE   工程。   
  •     
  •     
  •   将缺省的窗体的名称修改为   frmPeerA。   
  •     
  •     
  •   将窗体的标题修改为“Peer   A”。   
  •     
  •     
  •   在窗体中放入一个   Winsock   控件,并将其命名为   udpPeerA。   
  •     
  •     
  •   在“属性”页上,单击“协议”并将协议修改为   UDPProtocol。   
  •     
  •     
  •   在窗体中添加两个   TextBox   控件。将第一个命名为   txtSend,第二个命名为   txtOutput。   
  •     
  •     
  •   为窗体增加如下的代码。     
  •   Private   Sub   Form_Load()   
  •   '控件的名字为   udpPeerA   
  •   With   udpPeerA   
  •   '重点:必须将   RemoteHost   的值   
  •   '修改为计算机的名字。   
  •   .RemoteHost=   "PeerB"     
  •   .RemotePort   =   1001       '连接的端口号。   
  •   .Bind   1002                                 '绑定到本地的端口。   
  •   End   With   
  •   frmPeerB.Show                                   '显示第二个窗体。   
  •   End   Sub   
  •     
  •   Private   Sub   txtSend_Change()   
  •   '在键入文本时,立即将其发送出去。   
  •   udpPeerA.SendData   txtSend.Text   
  •   End   Sub   
  •     
  •   Private   Sub   udpPeerA_DataArrival   _   
  •   (ByVal   bytesTotal   As   Long)   
  •   Dim   strData   As   String   
  •   udpPeerA.GetData   strData   
  •   txtOutput.Text   =   strData   
  •   End   Sub   
  •     
  •   要创建第二个   UDP   伙伴,请按照以下步骤执行:     
  •     
  •   在工程中添加一个标准窗体。   
  •     
  •     
  •   将窗体的名字修改为   frmPeerB。   
  •     
  •     
  •   将窗体的标题修改为“Peer   B”。   
  •     
  •     
  •   在窗体中放入一个   Winsock   控件,并将其命名为   udpPeerB。   
  •     
  •     
  •   在“属性”页上,单击“协议”并将协议修改为“UDPProtocol”。   
  •     
  •     
  •   在窗体上添加两个   TextBox   控件。将第一个命名为   txtSend,第二个命名为   txtOutput。   
  •     
  •     
  •   在窗体中添加如下的代码。     
  •   Private   Sub   Form_Load()   
  •   '控件的名字为   udpPeerB。   
  •   With   udpPeerB   
  •   '重点:必须将   RemoteHost   的值改为   
  •   '计算机的名字。   
  •   .RemoteHost=   "PeerA"   
  •   .RemotePort   =   1002         '要连接的端口。   
  •   .Bind   1001                                 '绑定到本地的端口上。   
  •   End   With   
  •   End   Sub   
  •     
  •   Private   Sub   txtSend_Change()   
  •   '在键入后立即发送文本。   
  •   udpPeerB.SendData   txtSend.Text   
  •   End   Sub   
  •     
  •   Private   Sub   udpPeerB_DataArrival   _   
  •   (ByVal   bytesTotal   As   Long)   
  •   Dim   strData   As   String   
  •   udpPeerB.GetData   strData   
  •   txtOutput.Text   =   strData   
  •   End   Sub   
  •     
  •   如果要试用上面的例子,按   F5   键运行工程,然后在两个窗体的   txtSend   TextBox   中分别键入一些文本。键入的文字将出现在另一个窗体的   txtOutput   TextBox   中。   
  •     
  •   关于   Bind   方法   
  •   在上面的代码中,在创建   UDP   应用程序时调用了   Bind   方法,这是必须的。Bind   方法的作用是为控件“保留”一个本地端口。例如,如果将控件绑定到   1001   号端口,那么其它应用程序将不能使用该端口进行“监听”。该方法阻止其它应用程序使用同样的端口。   
  •     
  •   Bind   方法的第二个参数是任选的。如果计算机上存在多个网络适配器,可以用   LocalIP   参数来指定使用哪一个适配器。如果忽略该参数,控件使用的将是计算机上“控制面板”设置中“网络”控制面板对话框中列出的第一个适配器。   
  •     
  •   在使用   UDP   协议的时候,可以任意地改变   RemoteHost   和   RemotePort   属性,同时始终保持绑定在同一个   LocalPort   上。TCP   协议与此不同,在改变   RemoteHost   和   RemotePort   属性之前,必须先关闭连接。