茵蒂克絲
基礎(chǔ)概念
IP 地址
IP 是英文 Internet Protocol (網(wǎng)絡(luò)之間互連的協(xié)議)的縮寫,,也就是為計算機網(wǎng)絡(luò)相互連接進行通信而設(shè)計的協(xié)議,。任一系統(tǒng),,只要遵守 IP協(xié)議就可以與因特網(wǎng)互連互通。
所謂IP地址就是給每個遵循tcp/ip協(xié)議連接在Internet上的主機分配的一個32bit地址,。按照TCP/IP協(xié)議規(guī)定,,IP地址用二進制來表示,每個IP地址長32bit,,比特換算成字節(jié),,就是4個字節(jié)。為了方便人們的使用,,IP地址經(jīng)常被寫成十進制的形式,,中間使用符號 “.” 分開不同的字節(jié),如:192.168.1.1,。在因特網(wǎng)中,,主機的標識便是它ip地址。
常見的獲取服務(wù)器ip的方法是使用系統(tǒng)自帶的ping命令,。例,,打開cmd輸入:
ping www.baidu.com
輸出:
其中的 115.239.210.27 就是baidu服務(wù)器的地址了
服務(wù)端與客戶端
服務(wù)端與客戶端在計算機的世界里,凡是提供服務(wù)的一方我們稱為服務(wù)端(Server),,而接受服務(wù)的另一方我們稱作客戶端(Client),。
網(wǎng)站提供網(wǎng)頁數(shù)據(jù)的服務(wù),使用者接受網(wǎng)站所提供的數(shù)據(jù)服務(wù),,所以使用者在這里就是客戶端,,響應(yīng)使用者要求的網(wǎng)站即稱為服務(wù)端。
不過客戶端及服務(wù)端的關(guān)系不見得一定建立在兩臺分開的機器上,,同一臺機器中也有這種主從關(guān)系的存在,,提供服務(wù)的服務(wù)端及接受服務(wù)的客戶端也有可能都在同一臺機器上。
例如我們在提供網(wǎng)頁的服務(wù)器上執(zhí)行瀏覽器瀏覽本機所提供的網(wǎng)頁,,這樣在同一臺機器上就同時扮演服務(wù)端及客戶端,。
Socket
socket的英文原義是“孔”或“插座”。作為4BDS UNIX的進程通信機制,,取后一種意思,。通常也稱作"套接字",用于描述IP地址和端口,,是一個通信鏈的句柄,。
Scoket程勛分為服務(wù)端與客戶端,服務(wù)端程序監(jiān)聽端口,,等待客戶端程序的連接,。客戶端程序發(fā)起連接,等待服務(wù)端的相應(yīng),??蛻舳讼胍B接上服務(wù)端的話,需要 知道服務(wù)端的ip地址,。
例如,,客戶想要訪問百度網(wǎng)站的首頁,通過瀏覽器訪問http://www.baidu.com,。瀏覽器發(fā)出請求之后,,先是DNS服務(wù)器將百度的域名解析成ip地址之后,訪問到ip地址為115.239.210.27服務(wù)器的80端口(http協(xié)議默認在80端口),,請求發(fā)送后,,百度的服務(wù)器作為響應(yīng)將頁面的源代碼發(fā)送至客戶端(通過瀏覽器右鍵->源代碼,或者ctrl+u可以看到服務(wù)器返回的頁面源代碼),,隨后瀏覽器將源代碼渲染成頁面,。這樣用戶就看到了百度網(wǎng)站的首頁。
頭文件和庫文件
在windows系統(tǒng)上,,當前的Windows Socket接口是Windows Sockets 2,,所有接口函數(shù)都是有Ws2_32.dll導(dǎo)出。在進行程序設(shè)計時,,祥光的數(shù)據(jù)類型,、結(jié)構(gòu)定義、函數(shù)聲明等衛(wèi)浴頭文件winsock2.h中,,編譯時需要包含此文件,,并且連接到庫Ws2_32.lib。
常用函數(shù)
常見的socket函數(shù)
WSAStartup 初始化Ws2_32.lib庫WSACleanup 關(guān)閉Ws2_32.lib庫Socket 創(chuàng)建socketclosesocket 關(guān)閉socketsockaddr和sockaddr_in 結(jié)構(gòu)體socket地址bind 綁定listen 監(jiān)聽accept 接收connect 連接send 發(fā)送recv 獲取返回WSAStartup () 函數(shù)
WSAStartup函數(shù)的功能使加載Ws2_32.dll等Socket程序運行的環(huán)境,。在程序初始化后,,Socket程序運行所依賴的動態(tài)鏈接庫不一定已經(jīng)在家,WSAStartup保證了Socket 動態(tài)鏈接庫的加載,。
1 2 3 4 | int WSAStartup(
__in WORD wVersionRequested,
__out LPWSADATA lpWSAData
);
|
參數(shù)一 wVersionRequested
Socket程序庫的版本,,一般使用MAKEWORD(2,2)宏生成。
參數(shù)二 lpWSAData
輸出參數(shù),,指向 WSADATA 結(jié)構(gòu)的指針,,用于返回Socket庫初始化的信息。
返回值 用來判斷程序是否成功加載
WSACleanup () 函數(shù)
與 WSAStartup 相反,, WSACleanup 釋放Ws2_32.dll,,函數(shù)無參數(shù)。
Socket () 函數(shù)
Socket函數(shù)的功能是建立一個綁定到制定協(xié)議和傳輸類型的Socket,。
1 2 3 4 5 | SOCKET WSAAPI socket(
__in int af,
__in int type,
__in int protocol
);
|
參數(shù)一 af
address family的縮寫,,制定該Socket使用哪一種類型的網(wǎng)絡(luò)地址。可以是IPv4(AF_INET),,也可以是IPv6(AF_INET6),、藍牙(AF_BTM),、NetBios(AF_NETBIOS)等,。
參數(shù)二 type
設(shè)置傳輸類型,常見類型有 SOCK_STREAM,、 SOCK_DGRAM,、 SOCK_RAM、 SOCK_SEQPACKET 等,。SOCK_STREAM 類型是基于連接的(TCP),,所收的數(shù)據(jù)時數(shù)據(jù)流形式的,傳輸層的數(shù)據(jù)包已經(jīng)經(jīng)過處理,。SOCK_DGRAM是基于報文(UDP),。如果制定為SOCK_RAM,那么可以建立原始套接字,,所收到的數(shù)據(jù)是以數(shù)據(jù)包(包括包頭)的形式存在的,。
參數(shù)三 protocol
設(shè)置傳輸協(xié)議,常用的協(xié)議為 IPPROTO_TCP 和 IPPROTO_UDP,。
colsesocket() 函數(shù)
與 socket 函數(shù)對應(yīng),,用于關(guān)閉 socket
1 2 3 | int WSAAPI closesocket(
__in SOCKET s
);
|
參數(shù)一 s
指定要關(guān)閉的socket
sockaddr 和 sockaddr_in 結(jié)構(gòu)體
sockaddr、 SOCKADDR,、 sockaddr_in,、 SOCKADDR_IN 這 幾個結(jié)構(gòu)用于表示地址很端口。在IPv4下,,這幾個結(jié)構(gòu)體是可以通用的,。
1 2 3 4 5 6 7 8 9 10 | typedef struct sockaddr {
#if (_WIN32_WINNT < 0x0600)
u_short sa_family;
#else
ADDRESS_FAMILY sa_family; // Address family.
#endif //(_WIN32_WINNT < 0x0600)
CHAR sa_data[14]; // Up to 14 bytes of direct address.
} SOCKADDR, *PSOCKADDR, FAR *LPSOCKADDR;
|
1 2 3 4 5 6 7 8 9 10 11 12 | typedef struct sockaddr_in {
#if(_WIN32_WINNT < 0x0600)
short sin_family;
#else //(_WIN32_WINNT < 0x0600)
ADDRESS_FAMILY sin_family;
#endif //(_WIN32_WINNT < 0x0600)
USHORT sin_port;
IN_ADDR sin_addr;
CHAR sin_zero[8];
} SOCKADDR_IN, *PSOCKADDR_IN;
|
bind() 函數(shù)
服務(wù)器端,將Socket與網(wǎng)絡(luò)地址和端口綁定起來,,函數(shù)原型如下:
1 2 3 4 5 | int WSAAPI bind(
__in SOCKET s,
__in_bcount(namelen) const struct sockaddr FAR * name,
__in int namelen
);
|
參數(shù)一 s
要綁定的socket
參數(shù)二 name
要綁定的網(wǎng)絡(luò)地址結(jié)構(gòu)體
參數(shù)三 namelen
name參數(shù)所指向的結(jié)構(gòu)體的大小
listen() 函數(shù)
設(shè)置 socket 的狀態(tài)為監(jiān)聽,,使客戶端程序可以進行連接,函數(shù)原型:
1 2 3 4 | int WSAAPI listen(
__in SOCKET s,
__in int backlog
);
|
參數(shù)一 s
綁定的socket
參數(shù)二 backlog
指定最大的連接數(shù)
accept() 函數(shù)
接受客戶端的連接
1 2 3 4 5 | SOCKET WSAAPI accept(
__in SOCKET s,
__out_bcount_opt(*addrlen) struct sockaddr FAR * addr,
__inout_opt int FAR * addrlen
);
|
參數(shù)一 s
正在監(jiān)聽的socket,,該 socket 使用 listen() 設(shè)置,。
參數(shù)二 addr (可選)
指針,指向一緩沖區(qū),,其中接收為通訊層所知的連接實體的地址,。Addr參數(shù)的實際格式由套接口創(chuàng)建時所產(chǎn)生的地址族確定。
參數(shù)三 addrlen (可選)
指針,,指向存有addr地址長度的整形數(shù),。
返回:
成功:非負描述字
失敗:-1
accept 默認會阻塞進程,直到有客戶端建立連接后返回,它返回的是連接用的 socket ,。如果 accept 成功返回,,則服務(wù)器與客戶已經(jīng)正確建立連接了,此時服務(wù)器通過 accept 返回的 socket 來完成與客戶的通信,。
connect() 函數(shù)
connect函數(shù)的功能使與服務(wù)器建立連接,。這個函數(shù)只能由客戶端程序調(diào)用。
1 2 3 4 5 | int WSAAPI connect(
__in SOCKET s,
__in_bcount(namelen) const struct sockaddr FAR * name,
__in int namelen
);
|
參數(shù)一 s
由 socket 函數(shù)建立的套接字,。
參數(shù)二 name
指向sockaddr結(jié)構(gòu)體指針,,包括了所要連接的服務(wù)端的地址和端口等。
參數(shù)三 namelen
sockaddr結(jié)構(gòu)的長度
send() 函數(shù)
向連接的另一端發(fā)送數(shù)據(jù),,不論是客戶還是服務(wù)器應(yīng)用程序都用 send 函數(shù)來向 TCP 連接的另一端發(fā)送數(shù)據(jù),。
1 2 3 4 5 6 | int WSAAPI send(
__in SOCKET s,
__in_bcount(len) const char FAR * buf,
__in int len,
__in int flags
);
|
參數(shù)一 s
指定發(fā)送端socket描述符。
參數(shù)二 *buf
指明存放要發(fā)送的數(shù)據(jù)的緩沖區(qū),。
參數(shù)三 len
指明實際要發(fā)送的數(shù)據(jù)的字節(jié)數(shù),。
參數(shù)四 flags
指明發(fā)送的方法,常見宏MSG_DONTROUTE,、MSG_OOB等,,一般置0。
將*buf指向的字符串發(fā)送至客戶端
recv() 函數(shù)
不論是客戶還是服務(wù)器應(yīng)用程序都用 recv 函數(shù) 從 TCP 連接的另一端接收數(shù)據(jù),。
1 2 3 4 5 6 | int WSAAPI recv(
__in SOCKET s,
__out_bcount_part(len, return ) __out_data_source(NETWORK) char FAR * buf,
__in int len,
__in int flags
);
|
參數(shù)一 s
指定接收端socket描述符,;
參數(shù)二 *buf
指明一個緩沖區(qū),該緩沖區(qū)用來存放recv函數(shù)接收到的數(shù)據(jù),;
參數(shù)三 len
指明buf的長度,;
參數(shù)四 flags
指明接收的方法,常見宏 MSG_DONTROUTE,、 MSG_OOB 等,,一般置0。
獲取到客戶端返回的字符串并將其寫入到buf中
簡單的 socket 通信示例
服務(wù)端(Server)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | #include <Winsock2.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
void main()
{
int err; // 錯誤信息
int len;
char sendBuf[100]; // 發(fā)送至客戶端的字符串
char recvBuf[100]; // 接受客戶端返回的字符串
SOCKET sockServer; // 服務(wù)端 Socket
SOCKADDR_IN addrServer; // 服務(wù)端地址
SOCKET sockClient; // 客戶端 Scoket
SOCKADDR_IN addrClient; // 客戶端地址
WSADATA wsaData; // winsock 結(jié)構(gòu)體
WORD wVersionRequested; // winsock 的版本
// 配置 Windows Socket版本
wVersionRequested = MAKEWORD( 2, 2 );
// 初始化 Windows Socket
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
{
// 啟動錯誤,,程序結(jié)束
return ;
}
/*
* 確認WinSock DLL支持2.2
* 請注意如果DLL支持的版本大于2.2至2.2
* 它仍然會返回wVersion2.2的版本
*/
if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 )
{
// 啟動錯誤,,程序結(jié)束
WSACleanup(); // 終止Winsock 2 DLL (Ws2_32.dll) 的使用
return ;
}
// 定義服務(wù)器端socket
sockServer = socket(AF_INET, SOCK_STREAM, 0);
// 設(shè)置服務(wù)端 socket
addrServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // 本機IP
addrServer.sin_family = AF_INET; // 協(xié)議類型是INET
addrServer.sin_port = htons(6000); // 綁定端口6000
// 將服務(wù)器端socket綁定在本地端口
bind(sockServer, (SOCKADDR *)&addrServer, sizeof (SOCKADDR));
// Listen 監(jiān)聽端口
listen(sockServer, 5); // 5 為等待連接數(shù)目
printf ( "服務(wù)器已啟動:\n監(jiān)聽中...\n" );
len = sizeof (SOCKADDR);
// accept 會阻塞進程,直到有客戶端連接上來為止
sockClient = accept(sockServer, (SOCKADDR *)&addrClient, &len);
// 當客戶端連接上來時, 拼接如下字符串
sprintf (sendBuf, "歡迎 ip: %s 的用戶連接, 這里是 Lellansin 的服務(wù)器\n" , inet_ntoa(addrClient.sin_addr));
// 向客戶端發(fā)送字符串
send(sockClient, sendBuf, strlen (sendBuf) + 1, 0);
// 獲取客戶端返回的數(shù)據(jù)
recv(sockClient, recvBuf, 100, 0);
// 打印客戶端返回的數(shù)據(jù)
printf ( "%s\n" , recvBuf);
// 關(guān)閉socket
closesocket(sockClient);
getchar ();
}
|
啟動后防火墻有阻擋提示,,這里接受就可以了,。另外下圖是原來博主測試時截的圖,跟上面代碼的輸出部分稍稍有些區(qū)別,。
客戶端(Client)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | #include <Winsock2.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
void main()
{
int err;
char *message;
char recvBuf[100];
SOCKET sockClient; // 客戶端 Scoket
SOCKADDR_IN addrServer; // 服務(wù)端地址
WSADATA wsaData;
WORD wVersionRequested;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
{
return ;
}
if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 )
{
// 啟動錯誤,,程序結(jié)束
WSACleanup( );
return ;
}
// 新建客戶端 scoket
sockClient = socket(AF_INET, SOCK_STREAM, 0);
// 定義要連接的服務(wù)端地址
addrServer.sin_addr.S_un.S_addr = inet_addr( "127.0.0.1" ); // 目標IP (127.0.0.1是本機地址)
addrServer.sin_family = AF_INET; // 協(xié)議類型是INET
addrServer.sin_port = htons(6000); // 連接端口1234
// 讓 sockClient 連接到 服務(wù)端
connect(sockClient, (SOCKADDR *)&addrServer, sizeof (SOCKADDR));
// 從服務(wù)端獲取數(shù)據(jù)
recv(sockClient, recvBuf, 100, 0);
// 打印數(shù)據(jù)
printf ( "%s\n" , recvBuf);
message = "服務(wù)端你好~" ;
// 發(fā)送數(shù)據(jù)到服務(wù)端
send(sockClient, message, strlen (message) + 1, 0);
// 關(guān)閉socket
closesocket(sockClient);
WSACleanup();
getchar (); // 暫停
}
|
簡單的端口掃描程序
hostent結(jié)構(gòu)體
host entry的縮寫,,該結(jié)構(gòu)記錄主機的信息,包括主機名,、別名,、地址類型、地址長度和地址列表,。之所以主機的地址是一個列表的形式,,原因是當一個主機有多個網(wǎng)絡(luò)接口時會有多個地址。
1 2 3 4 5 6 7 8 | struct hostent {
char FAR * h_name; /* 主機正式名稱 */
char FAR * FAR * h_aliases; /* 主機別名 */
short h_addrtype; /* 地址類型 */
short h_length; /* 地址長度 */
char FAR * FAR * h_addr_list; /* 主機網(wǎng)絡(luò)地址指針 */
#define h_addr h_addr_list[0] /* 指向第一個地址 */
};
|
代碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | #include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#pragma comment(lib,"ws2_32.lib")
void Help( void );
int main( int argc, char *argv[])
{
WORD wVersion = MAKEWORD(2, 0);
WSADATA wsaData;
//sockaddr_in結(jié)構(gòu)體
struct sockaddr_in sin ;
int iFromPort;
int iToPort;
int iNowPort;
char *cHost;
HOSTENT *host_entry;
char *host_name;
char host_address[256];
SOCKET s;
int iOpenPort = 0;
int port[256], i;
if (argc != 4)
{
Help();
return -1;
}
iFromPort = atoi (argv[2]);
iToPort = atoi (argv[3]);
host_name = argv[1];
if (iFromPort > iToPort || iFromPort < 0 || iFromPort > 65535 || iToPort < 0 || iToPort > 65535)
{
printf ( "起始端口不能大于結(jié)束端口,且范圍為:1--65535 " );
return 0;
}
if ( WSAStartup(wVersion , &wsaData) )
{
printf ( "初始化失??!" );
return -1;
}
// 根據(jù)用戶輸入的域名來獲取服務(wù)器主機信息
host_entry = gethostbyname(host_name);
if (host_entry != 0)
{
wsprintf( host_address, "%d.%d.%d.%d" ,
(host_entry->h_addr_list[0][0] & 0x00ff),
(host_entry->h_addr_list[0][1] & 0x00ff),
(host_entry->h_addr_list[0][2] & 0x00ff),
(host_entry->h_addr_list[0][3] & 0x00ff)
);
printf ( "\n主機名稱:%s 主機地址:%s \n" , host_name, host_address);
}
cHost = host_address;
printf ( "======= 開始掃描 ======= \n" );
for (iNowPort = iFromPort; iNowPort <= iToPort; iNowPort++)
{
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == INVALID_SOCKET)
{
printf ( "create socket() failed!" );
WSACleanup();
}
sin .sin_family = AF_INET;
sin .sin_port = htons(iNowPort);
sin .sin_addr.S_un.S_addr = inet_addr(cHost);
if (connect(s, ( struct sockaddr *)& sin , sizeof ( sin )) == SOCKET_ERROR)
{
printf ( "%s -> %d:未開放 \n" , cHost, iNowPort);
closesocket(s);
}
else
{
printf ( "%s -> %d:開放 \n" , cHost, iNowPort);
port[iOpenPort] = iNowPort;
iOpenPort ++;
closesocket(s);
}
}
printf ( "======= 掃描結(jié)果 ======= \n" );
printf ( "主機:%s 掃描到%d個端口,分別是: \n" , host_name, iOpenPort);
for ( i = 0; i < iOpenPort; i++)
{
printf ( "%d " , port[i]);
}
//關(guān)閉socket
closesocket(s);
WSACleanup();
return 0;
}
//幫助函數(shù)
void Help()
{
printf ( "Usage: \n" );
printf ( "Port.exe <TargetIP> <BeginPort> <EndPort> \n" );
printf ( "Example: \n" );
printf ( "scan.exe 127.0.0.1 100 200 " );
}
|
函數(shù)列表
一、基本Socket函數(shù)
accept() 響應(yīng)連接請求,,返回一個連接socket,原來的socket返回監(jiān)聽狀態(tài)bind() 把一個socket綁定在某個端口上CloseSocket() 關(guān)閉套接字Connect() 連接GetPeerName() 得到連接在指定套接口上的對等通信方的名字GetSockName() 得到指定套接口上當前的名字GetSockopt() 得到與制定套接口相關(guān)的屬性選項htonl() 把32位的數(shù)字從主機字節(jié)順序轉(zhuǎn)換到網(wǎng)絡(luò)字節(jié)順序htons() 把16位的數(shù)字從主機字節(jié)順序轉(zhuǎn)換到網(wǎng)絡(luò)字節(jié)順序inet_addr() 把一個Internet標準的點分十進制地址轉(zhuǎn)換成Internet地址數(shù)值inet_ntoa() 把Internet地址轉(zhuǎn)換成點分十進制的字符串ioctlsocket() 為套接字提供控制listen() 監(jiān)聽套接字上連接請求的到來ntohl() 把32位的數(shù)字從網(wǎng)咯字節(jié)順序轉(zhuǎn)換為主機字節(jié)順序ntons() 把16位的數(shù)字從網(wǎng)咯字節(jié)順序轉(zhuǎn)換為主機字節(jié)順序recv() 從已經(jīng)連接的套接字接受數(shù)據(jù)recvfrom() 從已連接的或沒有連接的套接口接受數(shù)據(jù)select() 執(zhí)行同步IO多路復(fù)用send() 從已連接的套幾口發(fā)送數(shù)據(jù)sendto() 從已連接的或沒有連接的套接口發(fā)送數(shù)據(jù)setsockopt() 設(shè)置與指定套接口相關(guān)的屬性選項shutdown() 關(guān)閉一部分全雙工的鏈接socket() 創(chuàng)建并返回一個socket二,、獲取信息
Gethostbyaddr() 根據(jù)網(wǎng)絡(luò)地址得到對應(yīng)的名字(會有多個)和地址Gethostbyname() 根據(jù)主機名得到對應(yīng)的名字(會有多個)和地址gethostname() 得到本機主機名getservbyname() 根據(jù)服務(wù)的名字得到對應(yīng)的服務(wù)名和端口號getservbyport() 根據(jù)端口號得到對應(yīng)的服務(wù)名和端口號getprotobyname() 根據(jù)協(xié)議名得到對應(yīng)的協(xié)議名和數(shù)值getprotobynumber() 根據(jù)端口號得到對應(yīng)的協(xié)議名和數(shù)值三,、DLL操作
WSAStartup 初始化底層的windows Sockets DLLWSACleanup 從底層的Sockets DLL中撤銷注冊WSAAsyncSelect Select函數(shù)的異步版本WSAIsBlocking 確定底層的winsock DLL是否在該線程已經(jīng)被一個調(diào)用阻塞WSACancelBlockingCall 取消未完成的阻塞的API調(diào)用WSASetBlockingHook 為底層的windows sockets實現(xiàn)設(shè)置阻塞鉤子WSASetLastError 設(shè)置下一次的WSAGetLastError返回的錯誤信息WSAGetLastError 得到最近的一個windows sockets API調(diào)用錯誤的詳細信息WSAUnhookBlockingHook 恢復(fù)原始的阻塞鉤子WSACancelAsyncRequest 取消一個未完成的 WSAAsyncGetXByY 函數(shù)的實例