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

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