Visual Basic Winsock API 函数详解

1.WSAStartup 函数
为了在你的应用程序当中调用任何一个Winsock API 函数,首先第一件事情你就是必须通过WSAStartup函数完成对Winsock 服务的初始化,因此需要调用WSAStartup函数。
Declare Function WSAStartup Lib "ws2_32.dll"   (ByVal wVersionRequired As Long, 
                                                lpWSAData As WSAData) As Long



这个函数有两个参数: wVersionRequired 和 lpWSAData。wVersionRequired 参数定义Windows Sockets 提供能使用的最高版本,它的高位字节定义的是次版本号,低位字节定义的是主版本号。下面的2个Winsock版本在VB中使用的例子:

初始化1.1版本
lngRetVal = WSAStartup(&H101, udtWinsockData)

初始化2.2版本
lngRetVal = WSAStartup(&H202, udtWinsockData)

第二个参数是WSADATA 的数据结构 ,它是接收Windows Sockets 执行时的数据。
Type WSAData
  wVersion       As Integer
  wHighVersion   As Integer
  szDescription  As String * WSADESCRIPTION_LEN
  szSystemStatus As String * WSASYS_STATUS_LEN
  iMaxSockets    As Integer
  iMaxUdpDg      As Integer
  lpVendorInfo   As Long
End Type

数据成员的描述在下表中:
Field              描述
wVersion           Windows Sockets 版本信息。
wHighVersion       通过加载库文件得到的最高的支持Winsock 的版本,它通常和wVersion值相同。
szDescription      Windows Sockets 执行时的详细描述
szSystemStatus     包含了相关的状态和配置的信息
iMaxSockets        表示同时打开的socket最大数,为0表示没有限制。
iMaxUdpDg          表示同时打开的数据报最大数,为0表示没有限制。
lpVendorInfo       厂商指定信息预留 

在Winsock的1.1和2.2版本中没有lpVendorInfo的返回值。因为winsock 2支持多个传输协议,所以iMaxSockets 和iMaxUdpDg只能在仅支持TCP/TP的winsock1.1中使用。为了在Winsock 2中获得这些值,你可以使用WSAEnumProtocols 函数。

如果成功或者返回一个错误代码,则函数返回 0。

错误代码\t\t\t    含义
WSASYSNOTREADY                指出网络没有为传输准备好。
WSAVERNOTSUPPORTED            当前的WinSock实现不支持应用程序指定的Windows Sockets规范版本
WSAEINPROGRESS                一个阻塞WinSock调用正在进行
WSAEPROCLIM                   请求的协议没有在系统中配置或没有支持它的实现存在。
WSAEFAULT                     lpWSAData 不是有效的指针 



2.WSACleanup 函数
每次调用了WSAStartup函数,你都需要调用WSACleanup函数,通知系统来卸载库文件及清除已分配的资源,这个函数十分简单,没有任何参数:
Declare Function WSACleanup Lib "ws2_32.dll" () As Long



3.建立Socket函数

Declare Function socket Lib "ws2_32.dll" (ByVal af As Long, 
                                          ByVal s_type As Long,
                                          ByVal Protocol As Long) As Long

函数有3个参数定义建立何种socket,三个参数分别是:

Argument            Description                                       Enum Type 
af                  Address family specification.                     AddressFamily 
s_type              Type specification for the new socket.            SocketType 
Protocol            Protocol to be used with the socket               SocketProtocol
                    that is specific to the indicated address family.

AddressFamily:
    AF_UNSPEC = 0          '/* unspecified */
    AF_UNIX = 1            '/* local to host (pipes, portals) */
    AF_INET = 2            '/* internetwork: UDP, TCP, etc. */
    AF_IMPLINK = 3         '/* arpanet imp addresses */
    AF_PUP = 4             '/* pup protocols: e.g. BSP */
    AF_CHAOS = 5           '/* mit CHAOS protocols */
    AF_NS = 6              '/* XEROX NS protocols */
    AF_IPX = AF_NS         '/* IPX protocols: IPX, SPX, etc. */
    AF_ISO = 7             '/* ISO protocols */
    AF_OSI = AF_ISO        '/* OSI is ISO */
    AF_ECMA = 8            '/* european computer manufacturers */
    AF_DATAKIT = 9         '/* datakit protocols */
    AF_CCITT = 10          '/* CCITT protocols, X.25 etc */
    AF_SNA = 11            '/* IBM SNA */
    AF_DECnet = 12         '/* DECnet */
    AF_DLI = 13            '/* Direct data link interface */
    AF_LAT = 14            '/* LAT */
    AF_HYLINK = 15         '/* NSC Hyperchannel */
    AF_APPLETALK = 16      '/* AppleTalk */
    AF_NETBIOS = 17        '/* NetBios-style addresses */
    AF_VOICEVIEW = 18      '/* VoiceView */
    AF_FIREFOX = 19        '/* Protocols from Firefox */
    AF_UNKNOWN1 = 20       '/* Somebody is using this! */
    AF_BAN = 21            '/* Banyan */
    AF_ATM = 22            '/* Native ATM Services */
    AF_INET6 = 23          '/* Internetwork Version 6 */
    AF_CLUSTER = 24        '/* Microsoft Wolfpack */
    AF_12844 = 25          '/* IEEE 1284.4 WG AF */
    AF_MAX = 26

Socket types:
    SOCK_STREAM = 1       ' /* stream socket */
    SOCK_DGRAM = 2        ' /* datagram socket */
    SOCK_RAW = 3          ' /* raw-protocol interface */
    SOCK_RDM = 4          ' /* reliably-delivered message */
    SOCK_SEQPACKET = 5    ' /* sequenced packet stream */

Protocols:
    IPPROTO_IP = 0         '/* dummy for IP */
    IPPROTO_ICMP = 1       '/* control message protocol */
    IPPROTO_IGMP = 2       '/* internet group management protocol */
    IPPROTO_GGP = 3        '/* gateway^2 (deprecated) */
    IPPROTO_TCP = 6        '/* tcp */
    IPPROTO_PUP = 12       '/* pup */
    IPPROTO_UDP = 17       '/* user datagram protocol */
    IPPROTO_IDP = 22       '/* xns idp */
    IPPROTO_ND = 77        '/* UNOFFICIAL net disk proto */
    IPPROTO_RAW = 255      '/* raw IP packet */
    IPPROTO_MAX = 256

该函数可以建立使用特定协议的网络套接字,例如对于UDP协议可以这样写:
s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
s=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)


4.关闭Socket函数
Declare Function closesocket Lib "ws2_32.dll" (ByVal s As Long) As Long

函数有一个参数为建立socket时的Handle


5.连接函数
Declare Function connect Lib "ws2_32.dll" (ByVal s As Long,
                                           ByRef name As sockaddr_in,
                                           ByVal namelen As Long) As Long


参数
s     连接的socket句柄。
name       建立连接的地址。
namelen    连接地址的长度。 

返回值

成功时返回0。否则返回SOCKET_ERROR以及一个对应的错误号 Err.LastDllError。

显然在调用这个函数时我们需要知道socket句柄,将连接的电脑的端口号和主机名称(或主机IP地址)。我们知道Winsock 控件的Connect方法依靠两个变量:RemoteHost 和RemotePort。此方法不需要socket句柄,因其已经被封装在COM对象中。你也许认为connect函数应该也接受相同的变量设置,然而,事实并非如此。connect函数的主机地址和端口号的传送是依靠 sockaddr_in 结构。
Public Type sockaddr_in
   sin_family       As Integer
   sin_port As Integer
   sin_addr As Long
   sin_zero(1 To 8) As Byte
End Type


6.套接字帮定函数
Declare Function bind Lib "ws2_32.dll" (ByVal s As Long, _
                  ByRef name As sockaddr_in, _
                  ByRef namelen As Long) As Long

s是使用Socket函数创建好的套接字

name指向描述通信对象的结构体的指针

namelen是该结构的长度。

该结构体中的分量包括:

IP地址:对应name.sin_addr.s_addr
端口号:对应name.sin_port
端口号用于表示同一台计算机上不同的进程(即应用程序),其分配方法有两种:
第一种分配方法是,进程让系统为套接字自动分配一端口号,这只要在调用bind前将端口号指定为0即可。由系统自动分配的端口号位于1024~5000之间,而1~1023之间的任一TCP或UDP端口都是保留的,系统不允许任一进程使用保留端口,除非其有效用户ID是零(即超级用户)。
第二种分配方法是,进程为套接字指定一特定端口。这对于需要给套接字分配一众所周知的端口的服务器是很有用的。指定范围在1024~65536之间。
地址类型:对应name.sin_family,一般都赋成AF_INET,表示是internet地址(即IP 地址)。IP地址通常使用点分表示法表示,但它事实上一个32位的长整数,这两者之间可通过inet_addr()函数转换。


7.套接字监听函数
Declare Function listen Lib "ws2_32.dll" (ByVal s As Long, 
                                          ByVal backlog As Long) As Long

listen函数用来设定Socket为监听状态,这种状态表明Socket准备被连接了。注意,此函数一般在服务程序上使用,其中s是使用Socket函数创建好的套接字,backlog参数用于设定等待连接的客户端数。


8.接受连接请求
Declare Function accept Lib "ws2_32.dll" (ByVal s As Long, 
                                          ByRef addr As sockaddr_in, _
                                          ByRef addrlen As Long) As Long

服务端应用程序调用此函数来接受客户端Socket连接请求,accept()函数的返回值为一新的Socket,新Socket就可用来完成服务端和客户端之间的信息传递与接收,而原来Socket仍可以接受其他可户端的连接请求。


9.接收信息
Declare Function recv Lib "ws2_32.dll" (ByVal s As Long, _
                                        ByRef buf As Any, _
                                        ByVal buflen As Long, _
                                        ByVal flags As Long) As Long 

s    一个已连接的socket的识别符
buf   接受到的数据的缓冲区
len   缓冲区长度
flags 指定从哪调用的标识 

第一个参数是socket的句柄-为socket函数返回值。那就是说:我们需要告诉recv函数,哪一个socket正访问函数。

第二个参数是:函数执行之后能装载一些数据的缓冲区。但它不是必须要有足够的长度接收Winsock缓冲区的所有数据,缓冲区的大小限制为8192 字节 (8 Kbytes)。因此如果Winsock缓冲区的数据的大小大于recv函数的缓冲区,你必需多次调用此函数,直到获取所有的数据。

如果应用程序定义缓冲区的长度,则recv函数必须知道缓冲区可以存放多少字节。第三个参数就是为了这个目的。

最后一个参数是可选的,今天我们不使用。该参数有两个选择标志: MSG_PEEK 和 MSG_OOB,用于改变函数的行为。

MSG_PEEK 从输入数据中取数。数据拷入缓冲区,但不从输入队列中移走。函数返回当前准备接收的字节数。  
MSG_OOB 处理OOB(Out-of-band带外)数据。在网络上有两种类型的数据包,正常包和带外包。带外包可以通过检验一个TCP/IP包头的一个特定标志来决定。



10.发送信息

Declare Function send Lib "ws2_32.dll" (ByVal s As Long, _
                                        ByRef buf As Any, _
                                        ByVal buflen As Long, _
                                        ByVal flags As Long) As Long 

参数参看接收信息




服务器与客户机交互
目前最常用的方法是:服务程序在一个众所周知的地址(其中包括端口信息)监听对服务的请求,也就是说,服务进程一直处于休眠状态,直到一个客户对这个服务的地址提出了连接请求。这个时刻,服务程序被唤醒并对客户的请求作出适当的反应。注意,服务器与客户机之间的交互可以是面向连接的(基于流套接字),也可以是无连接的(基于数据报套接字)。


            服务器

           socket()
              |
            bind()
              |
           listen()                                       客户机
              |
              |                                           socket()
              |                     建立连接               |
           accept()   <-------------------------    connect()
              |                     请求数据               |
            recv()   <-----------------------------     send()
              |                                                          |
         处理服务请求                              |
              |                      应答数据               |
            send()    ------------------------------>   recv()
              |                                                          |
           close()                                                close()


Winsock API函数声明:

Public Declare Function accept Lib "Winsock.dll" _
  (ByVal s As Integer, addr As sockaddr, addrlen As Integer) As Integer
Public Declare Function bind Lib "Winsock.dll" _
  (ByVal s As Integer, addr As sockaddr, ByVal namelen As Integer) As Integer
Public Declare Function closesocket Lib "Winsock.dll" _
  (ByVal s As Integer) As Integer
Public Declare Function Connect Lib "Winsock.dll" Alias "connect" _
  (ByVal s As Integer, addr As sockaddr, ByVal namelen As Integer) As Integer
Public Declare Function ioctlsocket Lib "Winsock.dll" _
  (ByVal s As Integer, ByVal CMD As Long, argp As Long) As Integer
Public Declare Function getpeername Lib "Winsock.dll" _
  (ByVal s As Integer, sName As sockaddr, namelen As Integer) As Integer
Public Declare Function getsockname Lib "Winsock.dll" _
  (ByVal s As Integer, sName As sockaddr, namelen As Integer) As Integer
Public Declare Function getsockopt Lib "Winsock.dll" _
  (ByVal s As Integer, ByVal Level As Integer, ByVal optname As Integer, optval As Any, optlen As Integer) As Integer
Public Declare Function htonl Lib "Winsock.dll" _
  (ByVal hostlong As Long) As Long
Public Declare Function htons Lib "Winsock.dll" _
  (ByVal hostshort As Integer) As Integer
Public Declare Function inet_addr Lib "Winsock.dll" _
  (ByVal cp As String) As Long
Public Declare Function inet_ntoa Lib "Winsock.dll" _
  (ByVal inn As Long) As Long
Public Declare Function listen Lib "Winsock.dll" _
  (ByVal s As Integer, ByVal backlog As Integer) As Integer
Public Declare Function ntohl Lib "Winsock.dll" _
  (ByVal netlong As Long) As Long
Public Declare Function ntohs Lib "Winsock.dll" _
  (ByVal netshort As Integer) As Integer
Public Declare Function recv Lib "Winsock.dll" _
  (ByVal s As Integer, buf As Any, ByVal buflen As Integer, ByVal flags As Integer) As Integer
Public Declare Function recvfrom Lib "Winsock.dll" _
  (ByVal s As Integer, buf As Any, ByVal buflen As Integer, ByVal flags As Integer, from As sockaddr, fromlen As Integer) As Integer
Public Declare Function ws_select Lib "Winsock.dll" Alias "select" _
  (ByVal nfds As Integer, readfds As fd_set, writefds As fd_set, exceptfds As fd_set, timeout As timeval) As Integer
Public Declare Function Send Lib "Winsock.dll" Alias "send" _
  (ByVal s As Integer, buf As Any, ByVal buflen As Integer, ByVal flags As Integer) As Integer
Public Declare Function sendto Lib "Winsock.dll" _
  (ByVal s As Integer, buf As Any, ByVal buflen As Integer, ByVal flags As Integer, to_addr As sockaddr, ByVal tolen As Integer) As Integer
Public Declare Function setsockopt Lib "Winsock.dll" _
  (ByVal s As Integer, ByVal Level As Integer, ByVal optname As Integer, optval As Any, ByVal optlen As Integer) As Integer
Public Declare Function ShutDown Lib "Winsock.dll" Alias "shutdown" _
  (ByVal s As Integer, ByVal how As Integer) As Integer
Public Declare Function socket Lib "Winsock.dll" _
  (ByVal af As Integer, ByVal s_type As Integer, ByVal protocol As Integer) As Integer

Public Declare Function gethostbyaddr Lib "Winsock.dll" _
  (addr As Long, ByVal addr_len As Integer, ByVal addr_type As Integer) As Long
Public Declare Function gethostbyname Lib "Winsock.dll" _
  (ByVal host_name As String) As Long
Public Declare Function gethostname Lib "Winsock.dll" _
  (ByVal host_name As String, ByVal namelen As Integer) As Integer
Public Declare Function getservbyport Lib "Winsock.dll" _
  (ByVal Port As Integer, ByVal proto As String) As Long
Public Declare Function getservbyname Lib "Winsock.dll" _
  (ByVal serv_name As String, ByVal proto As String) As Long
Public Declare Function getprotobynumber Lib "Winsock.dll" _
  (ByVal proto As Integer) As Long
Public Declare Function getprotobyname Lib "Winsock.dll" _
  (ByVal proto_name As String) As Long



Public Declare Function WSAStartup Lib "Winsock.dll" _
  (ByVal wVR As Integer, lpWSAD As WSADataType) As Integer
Public Declare Function WSACleanup Lib "Winsock.dll" () As Integer
Public Declare Sub WSASetLastError Lib "Winsock.dll" _
  (ByVal iError As Integer)
Public Declare Function WSAGetLastError Lib "Winsock.dll" () As Integer
Public Declare Function WSAIsBlocking Lib "Winsock.dll" () As Integer
Public Declare Function WSAUnhookBlockingHook Lib "Winsock.dll" () As Integer
Public Declare Function WSASetBlockingHook Lib "Winsock.dll" _
  (ByVal lpBlockFunc As Long) As Long
Public Declare Function WSACancelBlockingCall Lib "Winsock.dll" () As Integer
Public Declare Function WSAAsyncGetServByName Lib "Winsock.dll" _
  (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal serv_name As String, ByVal proto As String, buf As Any, ByVal buflen As Integer) As Integer
Public Declare Function WSAAsyncGetServByPort Lib "Winsock.dll" _
  (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal Port As Integer, ByVal proto As String, buf As Any, ByVal buflen As Integer) As Integer
Public Declare Function WSAAsyncGetProtoByName Lib "Winsock.dll" _
  (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal proto_name As String, buf As Any, ByVal buflen As Integer) As Integer
Public Declare Function WSAAsyncGetProtoByNumber Lib "Winsock.dll" _
  (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal number As Integer, buf As Any, ByVal buflen As Integer) As Integer
Public Declare Function WSAAsyncGetHostByName Lib "Winsock.dll" _
  (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal host_name As String, buf As Any, ByVal buflen As Integer) As Integer
Public Declare Function WSAAsyncGetHostByAddr Lib "Winsock.dll" _
  (ByVal hwnd As Integer, ByVal wMsg As Integer, addr As Long, ByVal addr_len As Integer, ByVal addr_type As Integer, buf As Any, ByVal buflen As Integer) As Integer
Public Declare Function WSACancelAsyncRequest Lib "Winsock.dll" _
  (ByVal hAsyncTaskHandle As Integer) As Integer
Public Declare Function WSAAsyncSelect Lib "Winsock.dll" _
  (ByVal s As Integer, ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal lEvent As Long) As Integer
Public Declare Function WSARecvEx Lib "Winsock.dll" _
  (ByVal s As Integer, buf As Any, ByVal buflen As Integer, ByVal flags As Integer) As Integer

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章