跳到內容

Windows 程式設計/Winsock

來自華夏公益教科書,開放書籍,共建世界

Winsock 是 Windows 中處理 Berkely Socket API 的庫的名稱。從技術上講,這個庫不是 Win32 API 的一部分,儘管在編寫 Winsock 應用程式時需要考慮一些 Windows 特定的問題。

建立 Winsock 專案

[編輯 | 編輯原始碼]

可以透過包含 <winsock2.h> 標頭檔案將 Winsock 新增到您的程式設計專案中。此標頭檔案用於庫的 32 位版本。對於 16 位版本,包含檔案 <winsock.h>。

winsock.dll 是庫的 16 位版本,ws2_32.dll 是 32 位版本。您必須指示連結器連結到庫的適當版本。

初始化 Winsock

[編輯 | 編輯原始碼]

在呼叫任何 Winsock 例程之前,必須首先透過呼叫 WSAStartup 函式來初始化庫。此函式需要指向 WSADATA 結構的指標。您不需要初始化此結構,因為對 WSAStartup 的呼叫將填充結構的所有欄位。您可以選擇從該結構中讀取值,並在您的程式中使用結果。然而,這不是必需的。WSAStartup 還要求您指定要使用的 Winsock 版本。Winsock 的最新版本是 1.1 版,儘管庫的最新版本是 2.0 版。要指定此引數,請將主版本和次版本傳遞給 MAKEWORD 宏。以下是一個示例

WSADATA wd;
WSAStartup(MAKEWORD(2, 0), &wd);

以下是 WSADATA 結構的定義。從這個資料結構,您可以確定一些重要的系統指標,包括您的庫的版本,可用的最大併發套接字數量等。

typedef struct WSAData {
 WORD wVersion;
 WORD wHighVersion;
 char szDescription[WSADESCRIPTION_LEN+1];
 char szSystemStatus[WSASYS_STATUS_LEN+1];
 unsigned short iMaxSockets;
 unsigned short iMaxUdpDg;
 char FAR* lpVendorInfo;
} WSADATA, *LPWSADATA; 

WSAStartup 的定義如下

int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);

此函式在成功時返回零,並在失敗時返回非零。這些錯誤程式碼可以被處理,或者程式可以中止。

退出 Winsock

[編輯 | 編輯原始碼]

程式完成後,它必須呼叫 WSACleanup,以從列表中登出自己,並釋放庫使用的任何資源。WSACleanup 不接受任何引數,並在成功時返回零。非零返回值表示清理過程中發生錯誤。

套接字作為控制代碼

[編輯 | 編輯原始碼]

有人說,與 UNIX 不同,Win32 不允許使用檔案 I/O 函式讀取/寫入套接字。這隻有一半是對的。套接字不能使用標準庫函式(如 fread、fwrite、fprintf 等)訪問。但是,如果我們將 SOCKET 結構轉換為 HANDLE 結構,我們就可以使用 Win32 檔案 I/O API 來與套接字互動。例如,我們現在可以使用 ReadFile 和 WriteFile 來寫入套接字,並且我們在這些 API 周圍編寫的任何例程都可以用於寫入網路。

在 Win32 下,不要嘗試將 SOCKET 轉換為 FILE 型別,並使用 stdio.h 檔案函式。這將導致某種錯誤(最可能是錯誤錯誤)。

高階 Win32 套接字

[編輯 | 編輯原始碼]

Win32 擁有完整的套接字函式,包括 bind、accept、socket、listen 和 recv。但是,Win32 還提供了一些高階函式變體,這些變體允許使用高階操作模式。例如,使用高階套接字函式允許重疊 I/O 模式、非同步模式、事件等。這些函式可以在 MSDN 上檢視。

華夏公益教科書