CSDN博客

img shanhe

VB中的Winsock编程

发表于2004/6/24 10:01:00  7633人阅读

 

VB中的Winsock编程

 

一.引言

Socket原意为“插座”,用于计算机通信则代表一种点到点信息传输。早期用于Unix系统上的通信编程规范,通信双方由代表两点的“服务器”和“客户”组成,基于IP协议进行按照TCP或UDP规范进行信息交换。建立双方通信的过程即称建立一个“套接字(Socket)”,建立后利用得到的“套接字”进行各种信息的交流。随着Windows系统的流行,开始有人在原来的基础上移植到Windows平台上。微软在早期编写了基于Windows特征的(消息驱动等)“套接字”编程API,一般称其为“Winsock API”。当微软的ActiveX技术大行其道之后,Microsoft又提供了一个称为“Winsock”的ActiveX控件,方便了利用VB编程的程序员进行“套接字”编程,使得我们不必深入Socket细节就可进行点到点的通信。

下面,我们先接触一下此控件。

 

二.Winsocket控件详解

此控件对于用户在运行时不可见,提供了一个简单的途径访问TCP及UDP网络服务而无需了解底层细节棗你只需设置属性、在恰当的时候调用它提供的方法即可。

主要属性有:

BytesReceived:返回当前缓冲区中的字节数量, 我们可以使用 GetData 方法以接收数据. 只读且设计时不可用

LocalHostName:返回本机名字符串,设计时不可用。

LocalIP:返回以(xxx.xxx.xxx.xxx)格式表达的IP地址串。设计时不可用,运行时只读。

LocalPort :本机使用的地址, 可读写,设计时可用,Long型。对于客户, 如果无需指定端口,则用端口0发送数据。在此情况下,控件将随机选择一个端口。 在一个连接确定后,为TCP的端口。对于服务器, 指用于监听的端口。 如设置为0, 则用随机数。 在调用Listen 方法后,该属性自动包含用到的端口。端口0总是用于在两计算机间建立动态连接。客户希望通过端口0获得一个随机端口以“回调”连接服务器 。

Protocol :套接字类型,为TCP或UDP二者之一,缺省为TCP类型。设置为sckTCPProtocol 表示TCP 协议sckUDPProtocol表示UDP 协议。在此属性被重置之前需用Close方法关闭之。

RemoteHost:发送或接收数据的主机,你可提供主机名如: "FTP://ftp.microsoft.com" 或 一 IP地址串, 例如 "100.0.1.1"。

RemoteHostIP:远程主机的IP地址。对于客户程序, 在连接确定后使用Connect方法,此属性包含远程主机的IP名串。对于服务器程序, 在引入连接需求后 (ConnectionRequest 事件),此属性包含 IP 串。当使用UDP套接字 ,在 DataArrival 事件发生后, 此属性为发送UDP数据的机器 IP 地址串。

RemotePort:连接套接字端口值。例如通常HTTP应用使用80端口,FTP则使用21。

State:控件的状态, 只读且设计时不可用。可为以下值:

 

常量 描述

sckClosed 0 缺省值,关闭套接字

sckOpen 1 打开套接字

sckListening 2 正监听端口

sckConnectionPending 3 正在进行未定的连接

sckResolvingHost 4 正解析主机地址

sckHostResolved 5 主机地址已解析

sckConnecting 6 正在连接

sckConnected 7 已连接

sckClosing 8 连接关闭

sckError 9 错误

其它属性类似一般控件。

主要方法有:

Accept :仅用于TCP服务器应用。 此方法用于在引入一个连接时响应ConnectionRequest 事件。语法:object.Accept requestID返回值:Void。响应事件时必须传递RequestID参数给此方法,以生成新的Socket实例用于实际的信息传输。

Bind :设定LocalPort及 LocalIP用于 TCP 连接。 当你有多个协议适配器时使用。语法:object.Bind LocalPort, LocalIP。LocalPort 此端口用于连接,LocalIP 生成连接的IP地址。如果已设定相关属性,可不必携带相关参数。在调用Lisent方法之前调用此方法。

Close :在客户或服务器方关闭TCP连接。语法:object.Close。参数:无。返回值:Void。

GetData :接收存于可变类型中的数据块。返回值:Void。语法:object.GetData data, [type,] [maxLen]。Data:接收数据的变量,如果空间不够,将设置为空。Type:可选,接收的类型, 自行设置。MaxLen:可选参数。 设定接收数组或字符串类型数据的尺寸。如果参数省缺,将接收所有的数据。如果提供数组或字符串以外的数据类型,则忽略此参数。Type可以设置为常用的数据类型。通常在DataArrival 事件中使用该方法。此事件包含totalBytes 参数. 如果你设定的maxlen 小于totalBytes 参数,你将得到一个由10040表示的剩余字节将丢失的警告信息。

Listen :建立一个设置为监听模式的套接字。此方法仅用于TCP连接。语法:object.Listen

参数:无。返回值:Void。当调用Listen之后,引入一个连接时发生ConnectionRequest 事件。当处理 ConnectionRequest时, 应用程序必须使用Accpet方法来响应。

PeekData :同GetData类似但PeekData 不从输入队列中移去数据。此方法仅用于TCP连接。语法:object.PeekData data, [type,] [maxLen]

 

SendData :向远地主机发送主机。返回值:Void。语法:object.SendData data。Data:将要发送的数据,使用字节数组。当使用UNICODE格式串时将在发送之前转换为ANSI串 。

发生的事件有:

Close :发生于远程主机关闭连接。为了正确的关闭TCP连接应当使用Close方法。

Connect :当连接行动完成时。语法:object.Connect()。用此事件表明连接成功。

 

ConnectionRequest :发生于一个远端主机要求确定一个连接时。仅用于TCP 服务器应用。RemoteHostIP 及 RemotePort 属性在此事件后存储了关于客户机的信息。语法: object_ConnectionRequest (requestID As Long) 。requestID:引入的连接的请求标识。此参数传给Accept方法中的第二个控件实例。服务器可以决定是否认可该连接。如果引入 的连接未被认可,客户将受到一个Close事件。使用Accept方法接受引入的连接。

DataArrival :当新数据抵达时发生。语法:object_DataArrival (bytesTotal As Long)。BytesTotal,Long型。 总计收到的数据量。此事件在你调用GetData方法之前将不会再发生。仅在有新数据抵达时激活。你可以在任何时刻使用BytesReceived 属性检查多少数据有效。

Error :表明发生了错误。限于篇幅,错误码忽略。

SendComplete :当发送动作完成时发生。语法:object_SendComplete。参数:无。

SendProgress:当发送数据时产生本事件。语法:object_SendProgress (bytesSent As Long, bytesRemaining As Long)。BytesSent:本事件发生以来发送的数据量。BytesRemaining: 缓冲区中等待发送的数据。

 

三.Winsocket编程应用实例

可以看到,Winsocket控件允许我们采用两种传输协议进行通信。TCP协议允许你建立并维持同远端主机的连接,通过连接双方可以以“stream”方式传输数据。利用此种方式的客户必须要知道服务器的名字(RemoteHost属性),也要知道服务器正监听(Listening)的端口(RemotePort),然后调用Connect方法。服务器程序则必须设置本Scoket的监听端口(LocalPort),然后调用Listen方法;当客户要求建立一个连接时,服务器方产生ConnectionRequest事件,如果服务器想完成连接,则调用Accept方法认可。一旦连接建立成功,双方计算机都能利用SendData方法发送。当接收到数据时,发生DataArrival事件,我们可以在此事件中调用GetData方法接收数据。而如果采用UDP协议,则客户机设置本地监听端口(LocalPort属性),服务器计算机设置客户机的名字(RemoteHost)以及监听端口属性(RemotePort),然后即可调用SendData方法发送数据;客户机在DataArrival事件中使用GetData方法接收信息。

为了演示编程细节,特编写一个供两人使用的“Chat”应用程序:程序分客户和服务器两独立的部分。先启动服务器应用程序,然后启动客户程序,经过握手后建立连接,然后双方即可相互通信,且由于采用TCP协议可以实现信息的实时准确传输。

具体步骤如下:

服务器程序的编写:

建立标准工程,然后选Project下的components…,从弹出的对话框中选中Microsoft Winsock Control 5.0,确定后会在控件面板中多出一个名为Winscok的控件。此控件即本文的“主脚”。
将Form1的Caption属性改为“SockSrv”,在窗体上添加刚刚加入工程的Winsock控件。
分别加入三个Label和TextBox控件,一个Command控件,设置它们属性和作用见下:
Label1.Caption=”监听端口:”, Label2. Caption =” 客户消息:”,Label3. Caption =” 服务器消息:”

TextBox1.Text=”900”,此控件用于设置 Winsock的服务器端监听端口。

TextBox2.Text= “ ”,TextBox2. MultiLin=Ture,TextBox2.ScrollBar=2。控件通过设置Text属性为空格,可以使初始的信息为空白,MultiLin属性为True可以允许多行显示,可以实时显示服务器同客户之间的交流。设置ScrollBar属性为2,可以加入一个垂直滚动条,允许显示多行的信息。本控件的主要作用在于实时显示服务器、客户之间的交流内容。

TextBox3的属性设置同TextBox2,主要作用在于输入服务器用户的信息。

Command1的标题为“监听”,用于将服务器转于监听端口的连接请求状态。

添加代码,具体内容可设为如下:
在Form1.Load事件添加:Winsock1.LocalPort = Text1.Text,作用是将Text1所定义的监听端口设置给Winsock控件。

在Command1的Click事件中添加:

 

If Winsock1.State <> sckClosed Then Winsock1.Close ‘在当前套接字未关闭时将其关闭

Winsock1.Bind ‘将设置值生效

Winsock1.Listen ‘监听端口的连接请求

在Winscok的几个事件中添加代码:

Private Sub Winsock1_ConnectionRequest(ByVal requestID As Long)

If Winsock1.State <> sckClosed Then Winsock1.Close

Winsock1.Accept requestID ‘在监听的端口有连接请求发生时,立即调用Accept方法

‘认可连接,使之生效。

End Sub

Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)

Dim strData As String

Winsock1.GetData strData, vbString‘当有数据到达时,调用GetData方法接收之

Text2.Text = strData ‘将接收的内容更新显示在Text2中

End Sub

 

以上即是将服务器端的设置设定,下面我们来看看客户端的程序。

建立新的标准工程,按照上面的方法添加 Winsock控件至控件面板中。
修改工程名为“SckClient”,并添加Winsock控件至窗体中。
添加三个Label和Text控件,两个Command控件,它们的属性分别为:
label1.caption=“服务器的地址:”,Label2.caption=“服务器发送的信息”,label3.caption=“客户消息”。

Text1.text= “www.ysh.com”,此处即客户要与之通讯的服务器地址或名字,此处应该填写实际运行时的服务器的名字或者TCP/IP协议的IP地址。www.ysh.com是我的在我所处的局域网上的主机名。

Text2.MultiLin=True,这是为了能够多行显示服务器发出的信息。为了能够查看到服务器发出的所有信息,还应设置ScollBar属性为3。

Text3也应是一个允许多行显示的控件。

Command1和Comand2的Caption分别为“连接”、“断开”,用于决定Winsock的连接状态。

添加相应的代码:
在Form_Load()中输入:Winsock1.RemotePort = "900",用于确定同服务器建立套接字的端口。

在 Command1_Click()中输入:

If Winsock1.State <> sckClosed Then Winsock1.Close ‘如果套接字未关闭,先关闭之

Winsock1.RemoteHost = Text1.Text ‘确定服务器的主机名

Winsock1.Bind ‘绑定套接字属性

Winsock1.Connect ‘向服务器发出连接请求

Command1.Enabled = False ‘使Command1不可用

Command2.Enabled = True ‘现在可以使其断开

 

在Command2_Click()中输入代码:

Command1.Enabled = True

Command2.Enabled = False

Winsock1.Close ‘关闭当前套接字

对于Winsock控件的各个事件,可以参考以下代码:

Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)

Dim str As String

Winsock1.GetData str, vbString ‘按照字符串类型接收信息

Text2.Text = str ‘立即更新到Text2中

End Sub

Private Sub Winsock1_Connect() ‘在连接成功后弹出消息框

MsgBox "connected to server!"

End Sub

为了实时将Text3的内容反映到服务器的信息框,需要Text3_Change()输入如下代码:

If Winsock1.State = sckConnected Then Winsock1.SendData Text3.Text

 

通过以上的设置编写,服务器、客户双方的动作皆设置完毕,我们就可以在网络上进行通信了。先启动服务器,按下“连接”按钮,等待客户机的请求,然后启动客户,输入正确的服务器地址或主机名,按下“连接”按钮,当弹出一个消息框时,表明连接成功,此时无论在服务器还是客户的Text3中输入任何信息,在对方的Text2中均会实时显示,这样一个简单的“Chat”程序开始正常工作了。

 

 

四.程序说明

调试以上程序,需要一定的技巧。因为Winsock控件是基于网络的控件,所以在调试运行的机器上必须网络安装完好,并且TCP/IP协议要安装;同时又由于是基于C/S模式的应用,所以需要同时运行两个进程或者在两台已经通过TC/IP协议联网的机器上运行。单机上调试需要一定的技巧,我们可以同时启动两个VB,分别打开客户和服务器两个工程,设计完后通过任务切换启动它们。这样可以利用Windows95的多任务在单机上完成对网络仿真。

本程序只是简单的演示Winsock控件的功能,通过此例展示VB编程的强大功能。本例中限于篇幅未能详细完善错误捕获、安全检验等措施,需要在实用化过程中注意。

另外,本例仅限于两台机器之间的通信,通过添加多个Winsock实例,设置相应的端口,我们可以允许多人同时“登录”至服务器,真正实现聊天室的功能,届时没有必要花费巨额的上网费,您就可以“享受”到互联网的服务。而且本程序也可以在互联网上供两台机器使用以交流信息,通过设定同朋友约定的端口,你可以在上互联网后启动客户或服务器程序,在网上来个“即时通(信)”。

以上程序在Pwin98系统、VB5.0上通过。实际上我们还可以将此控件用于VFP、VC、PB等支持ActiveX控件的语言上。在此抛砖引玉,不当之处望诸位同仁指教。

==

1998?1999?写的,不记得了

0 0

相关博文

我的热门文章

img
取 消
img