WSAStartup()函數以及DLL的載入

2020-07-16 10:04:43
本節講解 Windows 下 DLL 的載入,學習 Linux Socket 的讀者可以跳過。
WinSock(Windows Socket)程式設計依賴於系統提供的動態連結庫(DLL),有兩個版本:
  • 較早的DLL是 wsock32.dll,大小為 28KB,對應的標頭檔案為 winsock1.h;
  • 最新的DLL是 ws2_32.dll,大小為 69KB,對應的標頭檔案為 winsock2.h。

幾乎所有的 Windows 作業系統都已經支援 ws2_32.dll,包括個人作業系統 Windows 95 OSR2、Windows 98、Windows Me、Windows 2000、XP、Vista、Win7、Win8、Win10 以及伺服器作業系統 Windows NT 4.0 SP4、Windows Server 2003、Windows Server 2008 等,所以你可以毫不猶豫地使用最新的 ws2_32.dll。

使用 DLL 之前必須把 DLL 載入到當前程式,你可以在編譯時載入,也可以在程式執行時載入,我們已在《動態連結庫DLL的載入:隱式載入(載入時載入)和顯式載入(執行時載入)》進行了講解。

這裡使用#pragma命令,在編譯時載入:
#pragma comment (lib, "ws2_32.lib")

WSAStartup() 函數

使用 DLL 之前,還需要呼叫 WSAStartup() 函數進行初始化,以指明 WinSock 規範的版本,它的原型為:
int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);
wVersionRequested 為 WinSock 規範的版本號,低位元組為主版本號,高位元組為副版本號(修正版本號);lpWSAData 為指向 WSAData 結構體的指標。

關於 WinSock 規範

WinSock 規範的最新版本號為 2.2,較早的有 2.1、2.0、1.1、1.0,ws2_32.dll 支援所有的規範,而 wsock32.dll 僅支援 1.0 和 1.1。

wsock32.dll 已經能夠很好的支援 TCP/IP 通訊程式的開發,ws2_32.dll 主要增加了對其他協定的支援,不過建議使用最新的 2.2 版本。

wVersionRequested 引數用來指明我們希望使用的版本號,它的型別為 WORD,等價於 unsigned short,是一個整數,所以需要用 MAKEWORD() 宏函數對版本號進行轉換。例如:
MAKEWORD(1, 2);  //主版本號為1,副版本號為2,返回 0x0201
MAKEWORD(2, 2);  //主版本號為2,副版本號為2,返回 0x0202

關於 WSAData 結構體

WSAStartup() 函數執行成功後,會將與 ws2_32.dll 有關的資訊寫入 WSAData 結構體變數。WSAData 的定義如下:
typedef struct WSAData {
    WORD           wVersion;  //ws2_32.dll 建議我們使用的版本號
    WORD           wHighVersion;  //ws2_32.dll 支援的最高版本號
    //一個以 null 結尾的字串,用來說明 ws2_32.dll 的實現以及廠商資訊
    char           szDescription[WSADESCRIPTION_LEN+1];
    //一個以 null 結尾的字串,用來說明 ws2_32.dll 的狀態以及設定資訊
    char           szSystemStatus[WSASYS_STATUS_LEN+1];
    unsigned short iMaxSockets;  //2.0以後不再使用
    unsigned short iMaxUdpDg;  //2.0以後不再使用
    char FAR       *lpVendorInfo;  //2.0以後不再使用
} WSADATA, *LPWSADATA;
最後3個成員已棄之不用,szDescription 和 szSystemStatus 包含的資訊基本沒有實用價值,讀者只需關注前兩個成員即可。請看下面的程式碼:
#include <stdio.h>
#include <winsock2.h>
#pragma comment (lib, "ws2_32.lib")

int main(){
    WSADATA wsaData;
    WSAStartup( MAKEWORD(2, 2), &wsaData);

    printf("wVersion: %d.%dn", LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion));
    printf("wHighVersion: %d.%dn", LOBYTE(wsaData.wHighVersion), HIBYTE(wsaData.wHighVersion));
    printf("szDescription: %sn", wsaData.szDescription);
    printf("szSystemStatus: %sn", wsaData.szSystemStatus);

    return 0;
}
執行結果:
wVersion: 2.2
wHighVersion: 2.2
szDescription: WinSock 2.0
szSystemStatus: Running

ws2_32.dll 支援的最高版本為 2.2,建議使用的版本也是 2.2。

綜上所述:WinSock 程式設計的第一步就是載入 ws2_32.dll,然後呼叫 WSAStartup() 函數進行初始化,並指明要使用的版本號。