《TCP IP協(xié)議與網(wǎng)絡(luò)編程》課件第8章 Winsock API_第1頁
《TCP IP協(xié)議與網(wǎng)絡(luò)編程》課件第8章 Winsock API_第2頁
《TCP IP協(xié)議與網(wǎng)絡(luò)編程》課件第8章 Winsock API_第3頁
《TCP IP協(xié)議與網(wǎng)絡(luò)編程》課件第8章 Winsock API_第4頁
《TCP IP協(xié)議與網(wǎng)絡(luò)編程》課件第8章 Winsock API_第5頁
已閱讀5頁,還剩231頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

第8章WinsockAPI8.1字節(jié)排序函數(shù)8.2IP地址轉(zhuǎn)換函數(shù)8.3網(wǎng)絡(luò)信息獲取函數(shù)(數(shù)據(jù)庫函數(shù))8.4套接口選項(xiàng)函數(shù)8.5套接口I/O處理函數(shù)8.6事件對(duì)象I/O管理8.7錯(cuò)誤處理函數(shù)8.8Winsock2支持的其他函數(shù)習(xí)題8.1字節(jié)排序函數(shù) 8.1.14字節(jié)主機(jī)字節(jié)順序的數(shù)轉(zhuǎn)化為網(wǎng)絡(luò)字節(jié)順序——htonl(?)和WSAHtonl(?) 1.函數(shù)格式 在Winsock1中提供的htonl(?)函數(shù)的格式是:u_longhtonl( u_longhostlong);

在Winsock2中提供的WSAHtonl(?)函數(shù)的擴(kuò)展格式是:intWSAHtonl( SOCKETs, u_longhostlong, u_longFAR*lpnetlong ); 2.函數(shù)參數(shù)說明 這兩個(gè)函數(shù)中各參數(shù)的說明如下: ●?hostlong:傳入?yún)?shù),它是一個(gè)用主機(jī)字節(jié)順序表示的將要被轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)順序的32位數(shù)(即4個(gè)字節(jié)的數(shù)),u_long表示無符號(hào)長整型數(shù)。 ●?s:傳入?yún)?shù),在Winsock2提供的擴(kuò)展格式中增加了標(biāo)識(shí)套接口的描述字。 ●?lpnetlong:傳出參數(shù),一個(gè)指向32位的網(wǎng)絡(luò)字節(jié)順序數(shù)的指針。 3.函數(shù)返回信息 這兩個(gè)函數(shù)的返回值差別較大,在使用時(shí)一定要注意。 對(duì)于htonl(?)函數(shù)來說,如果該函數(shù)被調(diào)用時(shí)正確執(zhí)行,則這個(gè)函數(shù)返回一個(gè)32位的TCP/IP網(wǎng)絡(luò)字節(jié)順序的數(shù)。 對(duì)于WSAHtonl(?)函數(shù)來說,如果該函數(shù)被調(diào)用時(shí)正確執(zhí)行,則這個(gè)函數(shù)的返回值為0,函數(shù)返回的32位網(wǎng)絡(luò)字節(jié)順序的數(shù)據(jù)是指針參數(shù)lpnetlong所指向的數(shù)。如果在調(diào)用時(shí)該函數(shù)發(fā)生錯(cuò)誤,則返回SOCKET_ERROR錯(cuò)誤信息,可以進(jìn)一步使用WSAGetLastError(?)函數(shù)取得對(duì)該錯(cuò)誤的具體描述。錯(cuò)誤代碼如下: ●?WSANOTINITIALISED:在調(diào)用本API之前應(yīng)成功調(diào)用WSAStartup(?)。 ●?WSAENETDOWN:網(wǎng)絡(luò)子系統(tǒng)失效。 ●?WSAENOTSOCK:描述字不是一個(gè)套接口。 ●?WSAEFAULT:指針參數(shù)lpnetlong不在有效的用戶地址空間中。

4.函數(shù)使用說明 該函數(shù)的使用比較簡單,主要用來將一個(gè)32位的IP地址從主機(jī)字節(jié)順序轉(zhuǎn)化為網(wǎng)絡(luò)字節(jié)順序,具體用法可以參考第7章的網(wǎng)絡(luò)程序?qū)嵗?8.1.22字節(jié)主機(jī)字節(jié)順序的數(shù)轉(zhuǎn)化為網(wǎng)絡(luò)字節(jié)順序——htons(?)和WSAHtons(?) 1.函數(shù)格式在Winsock1中提供的htons(?)函數(shù)的格式是:

u_shorthtons(u_shorthostshort);

在Winsock2中提供的WSAHtons(?)函數(shù)的擴(kuò)展格式是:

u_shortWSAHtons(SOCKETs,u_shorthostshort,u_shortFAR*lpnetshort); 2.函數(shù)參數(shù)說明 這兩個(gè)函數(shù)中各參數(shù)的說明如下: ●?hostshort:傳入?yún)?shù),它是一個(gè)以主機(jī)字節(jié)順序表示的將要被轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)順序的16位數(shù)(即2字節(jié)數(shù)),u_short表示無符號(hào)短整型數(shù)。 ●?s:傳入?yún)?shù),Winsock2提供的擴(kuò)展格式中增加的標(biāo)識(shí)套接口的描述字。 ●?lpnetshort:傳出參數(shù),一個(gè)指向16位網(wǎng)絡(luò)字節(jié)順序數(shù)的指針。 3.函數(shù)返回信息

htons(?)函數(shù)如果被調(diào)用時(shí)正確執(zhí)行,則這個(gè)函數(shù)返回一個(gè)16位TCP/IP網(wǎng)絡(luò)字節(jié)順序的數(shù)。

WSAHtons(?)函數(shù)如果被調(diào)用時(shí)正確執(zhí)行,則這個(gè)函數(shù)返回0,函數(shù)返回的16位網(wǎng)絡(luò)字節(jié)順序的數(shù)據(jù)是指針參數(shù)lpnetshort所指向的數(shù)。如果在調(diào)用時(shí)該函數(shù)發(fā)生錯(cuò)誤,則返回SOCKET_ERROR錯(cuò)誤信息,可以進(jìn)一步使用WSAGetLastError(?)函數(shù)取得對(duì)該錯(cuò)誤的具體描述。錯(cuò)誤代碼與WSAHtonl(?)函數(shù)的錯(cuò)誤代碼類似。

4.函數(shù)使用說明 該函數(shù)一般用來將一個(gè)16位的TCP或UDP端口號(hào)從主機(jī)字節(jié)順序轉(zhuǎn)化為網(wǎng)絡(luò)字節(jié)順序,用法可以參考第7章的程序?qū)嵗?8.1.34字節(jié)網(wǎng)絡(luò)字節(jié)順序的數(shù)轉(zhuǎn)化為主機(jī)字節(jié)順序——ntohl(?)和WSANtohl(?) 1.函數(shù)格式 在Winsock1中提供的ntohl(?)函數(shù)的格式是:

u_longntohl( u_longnetlong );

在Winsock2中提供的WSANtohl(?)函數(shù)的擴(kuò)展格式是:

u_longWSANtohl( SOCKETs, u_longnetlong, u_longFAR*lphostlong ); 2.函數(shù)參數(shù)說明 這兩個(gè)函數(shù)的參數(shù)說明如下: ●?netlong:傳入?yún)?shù),一個(gè)以網(wǎng)絡(luò)字節(jié)順序表示的32位數(shù)。 ●?s:傳入?yún)?shù),在Winsock2中提供的擴(kuò)充格式中增加的標(biāo)識(shí)套接口的描述字。 ●?lphostlong:傳出參數(shù),指向一個(gè)32位主機(jī)字節(jié)順序數(shù)的指針。

3.函數(shù)返回信息

ntohl(?)函數(shù)在調(diào)用成功后,返回一個(gè)主機(jī)字節(jié)順序的32位數(shù)。 WSANtohl(?)函數(shù)在調(diào)用正確時(shí)返回0,函數(shù)返回的32位主機(jī)字節(jié)順序的數(shù)據(jù)是指針參數(shù)lphostlong所指向的數(shù)。如果調(diào)用錯(cuò)誤,則返回錯(cuò)誤信息SOCKET_ERROR,可以進(jìn)一步使用WSAGetLastError(?)函數(shù)取得對(duì)該錯(cuò)誤的具體描述。具體錯(cuò)誤代碼與WSAHtonl(?)函數(shù)的錯(cuò)誤代碼類似。

4.函數(shù)使用說明 該函數(shù)常用來將一個(gè)網(wǎng)絡(luò)字節(jié)順序表示的32位IP地址轉(zhuǎn)化為主機(jī)字節(jié)順序。 8.1.42字節(jié)網(wǎng)絡(luò)字節(jié)順序的數(shù)轉(zhuǎn)化為主機(jī)字節(jié)順序——ntohs(?)和WSANtohs(?) 1.函數(shù)格式 在Winsock1中提供的ntohs(?)函數(shù)的格式是:

u_shortntohs( u_shortnetshort );

在Winsock2中提供的WSANtohs(?)函數(shù)的擴(kuò)展格式是:

u_shortWSANtohs( SOCKETs, u_shortnetshort, u_shortFAR*lphostshort ); 2.函數(shù)參數(shù)說明 這兩個(gè)函數(shù)的參數(shù)說明如下: ●?netshort:傳入?yún)?shù),一個(gè)以網(wǎng)絡(luò)字節(jié)順序表示的16位數(shù)。 ●?s:傳入?yún)?shù),在Winsock2提供的擴(kuò)充格式中增加的一個(gè)標(biāo)識(shí)套接口的描述字。 ●?lphostshort:傳出參數(shù),指向一個(gè)16位主機(jī)字節(jié)順序數(shù)的指針。 3.函數(shù)返回信息

ntohs(?)函數(shù)在調(diào)用成功后,返回一個(gè)主機(jī)字節(jié)順序的16位數(shù)。

WSANtohs(?)函數(shù)在調(diào)用正確時(shí)返回0,函數(shù)返回的16位主機(jī)字節(jié)順序的數(shù)據(jù)是指針參數(shù)lphostshort所指向的數(shù)。如果調(diào)用錯(cuò)誤,則返回錯(cuò)誤信息SOCKET_ERROR,可以進(jìn)一步使用WSAGetLastError(?)函數(shù)取得對(duì)該錯(cuò)誤的具體描述。具體錯(cuò)誤代碼與WSAHtonl(?)函數(shù)的錯(cuò)誤代碼類似。

4.函數(shù)使用說明 該函數(shù)常用來將一個(gè)網(wǎng)絡(luò)字節(jié)順序表示的16位TCP或UDP端口號(hào)轉(zhuǎn)化為主機(jī)字節(jié)順序。8.2IP地址轉(zhuǎn)換函數(shù) 8.2.1點(diǎn)分十進(jìn)制數(shù)表示的IP地址轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)順序的IP地址——inet_addr(?) 1.函數(shù)格式

inet_addr(?)函數(shù)的格式如下:

unsignedlonginet_addr(constcharFAR*cp ); 2.函數(shù)參數(shù)說明 該函數(shù)中的參數(shù)cp為傳入?yún)?shù),是一個(gè)以“.”間隔的字符串,即一個(gè)點(diǎn)分十進(jìn)制數(shù)表示的IP地址。

3.函數(shù)返回信息 該函數(shù)調(diào)用成功后,返回一個(gè)無符號(hào)長整型數(shù)(UnsignedLong),它是以網(wǎng)絡(luò)字節(jié)順序表示的32位二進(jìn)制IP地址。如果傳入的字符串不是一個(gè)合法的Internet地址,如當(dāng)“a.b.c.d”地址中任一項(xiàng)超過255時(shí),則inet_addr(?)返回INADDR_NONE提示信息。 4.函數(shù)使用說明 當(dāng)IP地址用點(diǎn)分十進(jìn)制數(shù)表示時(shí),即4個(gè)字節(jié)的數(shù)以“.”間隔,則用這種格式書寫的IP地址可有下列4種表示方式。

(1)?a.b.c.d:當(dāng)四個(gè)部分都有固定的值時(shí),則每一個(gè)部分被解釋成一個(gè)字節(jié)的數(shù)據(jù),從左到右組成Internet4字節(jié)地址。請(qǐng)注意,當(dāng)一個(gè)Internet地址在Intel機(jī)器上表示成一個(gè)32位整型數(shù)時(shí),則上述數(shù)據(jù)在計(jì)算機(jī)內(nèi)部的表示為“d.c.b.a”。這是因?yàn)樵贗ntel處理器內(nèi)部,字中的字節(jié)是按由低到高的順序存儲(chǔ)的,即“小序在前”。 (2)a.b.c:對(duì)于一個(gè)只有三個(gè)部分組成的IP地址,最后一部分被解釋成16位數(shù)據(jù),并作為網(wǎng)絡(luò)地址最右邊的兩個(gè)字節(jié)。

(3)a.b:對(duì)于一個(gè)只有兩個(gè)部分組成的IP地址,最后一部分解釋成24位數(shù)據(jù),并作為網(wǎng)絡(luò)地址最右邊的三個(gè)字節(jié)。

(4)a:對(duì)于一個(gè)僅有一個(gè)部分的IP地址,將它的值直接存入網(wǎng)絡(luò)地址而不做任何字節(jié)重組。 該函數(shù)的用法見第7章中的客戶程序?qū)嵗?8.2.2網(wǎng)絡(luò)字節(jié)順序的IP地址轉(zhuǎn)換為點(diǎn)分十進(jìn)制數(shù)表示的IP地址——inet_ntoa(?) 1.函數(shù)格式

inet_ntoa(?)函數(shù)的格式如下:

char*inet_ntoa( structin_addrin ); 2.函數(shù)參數(shù)說明 該函數(shù)中的參數(shù)in為傳入?yún)?shù),表示一個(gè)結(jié)構(gòu)型的IP主機(jī)地址。 3.函數(shù)返回信息 該函數(shù)調(diào)用成功后,返回一個(gè)指向字符的指針,該指針指向一個(gè)文本型的緩沖區(qū),緩沖區(qū)中存有用點(diǎn)分十進(jìn)制形式表示的IP地址。如果函數(shù)調(diào)用失敗的話,則返回一個(gè)空指針(NULL)。

4.函數(shù)使用說明 該函數(shù)的用法參見第7章中的服務(wù)器程序?qū)嵗?.3網(wǎng)絡(luò)信息獲取函數(shù)(數(shù)據(jù)庫函數(shù)) 8.3.1獲得主機(jī)名——gethostname(?) gethostname(?)函數(shù)用來取得一臺(tái)主機(jī)的名稱信息。

1.函數(shù)格式 該函數(shù)的格式如下:

intgethostname( charFAR*name, intnamelen ); 2.函數(shù)參數(shù)說明

gethostname(?)函數(shù)中各參數(shù)的說明如下: ●?name:傳出參數(shù),一個(gè)指向?qū)⒁娣胖鳈C(jī)名的緩沖區(qū)指針,當(dāng)函數(shù)調(diào)用完成時(shí),主機(jī)名被存入該緩沖區(qū)中。 ●?namelen:傳入?yún)?shù),緩沖區(qū)的長度。

3.函數(shù)返回信息 如果函數(shù)調(diào)用時(shí)沒有發(fā)生錯(cuò)誤,則gethostname(?)函數(shù)返回0。如果函數(shù)調(diào)用失敗,則返回SOCKET_ERROR錯(cuò)誤信息。應(yīng)用程序可以通過WSAGetLastError(?)來得到一個(gè)特定的錯(cuò)誤代碼,錯(cuò)誤代碼說明如下:

●?WSAEFAULT:名字長度參數(shù)太小。 ●?WSANOTINTIALISED:在應(yīng)用這個(gè)API前,必須成功調(diào)用WSAStartup(?)。 ●?WSAENETDOWN:WindowsSockets實(shí)現(xiàn)檢測(cè)到了網(wǎng)絡(luò)子系統(tǒng)的錯(cuò)誤。 ●?WSAEINPROGRESS:一個(gè)阻塞的WindowsSockets操作正在進(jìn)行。

4.函數(shù)使用說明 該函數(shù)把本地主機(jī)名存放入由name參數(shù)指定的緩沖區(qū)中。主機(jī)名的形式取決于WindowsSockets系統(tǒng)的實(shí)現(xiàn),它可能是一個(gè)簡單的主機(jī)名,或者是一個(gè)域名。不管是哪種形式,該函數(shù)返回的名字必定可以在gethostbyname(?)和WSAAsyncGetHostByName(?)函數(shù)中使用。 8.3.2獲得與套接口相連的遠(yuǎn)程協(xié)議地址——getpeername(?) 1.函數(shù)格式

getpeername(?)函數(shù)的格式如下:

intgetpeername( SOCKETs, structsockaddrFAR*name, intFAR*namelen ); 2.函數(shù)參數(shù)說明 該函數(shù)中各參數(shù)的說明如下: ●?s:傳入?yún)?shù),一個(gè)已建立連接的套接口描述字。 ●?name:傳出參數(shù),指向返回的遠(yuǎn)程協(xié)議地址。 ●?namelen:傳出參數(shù),遠(yuǎn)程協(xié)議地址長度。

3.函數(shù)返回信息 調(diào)用該函數(shù)時(shí)若無錯(cuò)誤發(fā)生,則getpeername(?)函數(shù)返回0。如果調(diào)用失敗,則返回SOCKET_ERROR錯(cuò)誤信息,應(yīng)用程序可通過調(diào)用WSAGetLastError(?)函數(shù)來獲取對(duì)該錯(cuò)誤的進(jìn)一步描述??色@得的錯(cuò)誤代碼如下: ●?WSANOTINITIALISED:在使用此API之前應(yīng)成功調(diào)用WSAStartup(?)。 ●?WSAENETDOWN:Windows套接口實(shí)現(xiàn)檢測(cè)到網(wǎng)絡(luò)子系統(tǒng)失效。 ●?WSAEFAULT:namelen參數(shù)不夠大。 ●?WSAEINPROGRESS:一個(gè)阻塞的Windows套接口調(diào)用正在運(yùn)行中。 ●?WSAENOTCONN:套接口未建立連接。 ●?WSAENOTSOCK:描述字不是一個(gè)套接口。 4.函數(shù)使用說明

getpeername(?)函數(shù)用于從套接口s中獲取與它綁定的遠(yuǎn)程協(xié)議的地址信息,并把它存放在sockaddr類型的name結(jié)構(gòu)中。它只能用于已經(jīng)建立連接的套接口。對(duì)于數(shù)據(jù)報(bào)類型的套接口來說,它只能返回先前調(diào)用connect(?)函數(shù)時(shí)使用的對(duì)等端信息,在sendto(?)函數(shù)中使用過的對(duì)等端信息不能被返回。 8.3.3獲得套接口本地協(xié)議地址——getsockname(?) 1.函數(shù)格式

getsockname(?)函數(shù)的格式如下:

intgetsockname( SOCKETs, structsockaddrFAR*name, intFAR*namelen ); 2.函數(shù)參數(shù)說明 該函數(shù)的參數(shù)說明如下: ●?s:傳入?yún)?shù),標(biāo)識(shí)一個(gè)套接口的描述字。 ●?name:傳出參數(shù),指向返回的本地協(xié)議地址的指針。 ●?namelen:傳出參數(shù),本地協(xié)議地址長度。當(dāng)函數(shù)調(diào)用完成時(shí),??它可以返回實(shí)際的本地地址長度。 3.函數(shù)返回信息 調(diào)用該函數(shù)時(shí)若無錯(cuò)誤發(fā)生,則getsockname(?)函數(shù)返回0。如果調(diào)用失敗,則返回SOCKET_ERROR錯(cuò)誤信息,應(yīng)用程序可通過WSAGetLastError(?)函數(shù)來獲取如下的錯(cuò)誤代碼: ●?WSANOTINITIALISED:在使用此API之前應(yīng)成功調(diào)用WSAStartup(?)。 ●?WSAENETDOWN:Windows套接口實(shí)現(xiàn)檢測(cè)到網(wǎng)絡(luò)子系統(tǒng)失效。 ●?WSAEFAULT:namelen參數(shù)不夠大。 ●?WSAEINPROGRESS:一個(gè)阻塞的Windows套接口調(diào)用正在運(yùn)行中。 ●?WSAENOTSOCK:描述字不是一個(gè)套接口。 ●WSAEINVAL:套接口未用bind(?)捆綁。 4.函數(shù)使用說明

getsockname(?)函數(shù)用于獲取一個(gè)套接口的協(xié)議地址,它用于一個(gè)已綁定或已連接套接口。本調(diào)用特別適用于如下情況:未調(diào)用bind(?)就調(diào)用了connect(?),這時(shí)惟有g(shù)etsockname(?)調(diào)用可以獲知系統(tǒng)內(nèi)定的本地地址。在返回時(shí),namelen參數(shù)包含了名字的實(shí)際字節(jié)數(shù)。 若一個(gè)套接口與INADDR_ANY綁定,即該套接口可以用任意的主機(jī)地址,此時(shí)除非調(diào)用connect(?)或accept(?)來連接,否則getsockname(?)將不會(huì)返回主機(jī)IP地址的任何信息。除非套接口被連接,Windows套接口應(yīng)用程序不應(yīng)假設(shè)IP地址會(huì)從INADDR_ANY變成其他地址。這是因?yàn)閷?duì)于一個(gè)有多個(gè)IP地址的主機(jī)來說,除非套接口被連接,否則該套接口所用的IP地址是不可知的(即不能被確定是哪一個(gè))。 8.3.4根據(jù)主機(jī)名取得主機(jī)信息——gethostbyname(?)或WSAAsyncGetHostByName(?) gethostbyname(?)和WSAAsynGetHostByName(?)這兩個(gè)WinsockAPI函數(shù)從主機(jī)數(shù)據(jù)庫中取回與指定的主機(jī)名對(duì)應(yīng)的主機(jī)信息。這兩個(gè)函數(shù)均返回一個(gè)hostent結(jié)構(gòu)型的量,所以先介紹一下該結(jié)構(gòu)的格式。hostent結(jié)構(gòu)的定義如下:

structhostent{ char FAR*h_name; /*officialnameofhost*/ char FAR*FAR*h_aliases; /*aliaslist*/ short h_addrtype; /*hostaddresstype*/

shorth_length;/*lengthofaddress*/ char FAR*FAR*h_addr_list; /*listofaddresses*/ #define h_addrh_addr_list[0] /*address,forbackwardcompat*/ };

該結(jié)構(gòu)中各字段的含義如下: ●?h_name:該字段是正式的主機(jī)名。 ●?h_aliases:它是二維字符指針,返回一臺(tái)主機(jī)的所有別名(即別名列表)。 ●?h_addrtype:表示主機(jī)地址類型,如AF_INET表示IPv4地址。 ●?h_length:該字段可以返回主機(jī)地址的字節(jié)數(shù)。 ●?h_addr_list:該字段返回一個(gè)主機(jī)的所有IP地址,因?yàn)橐慌_(tái)主機(jī)可以分配若干個(gè)IP地址(當(dāng)然這主要是對(duì)服務(wù)器而言的)。這個(gè)數(shù)組中的每個(gè)地址都是按網(wǎng)絡(luò)字節(jié)順序返回的。一般情況下,應(yīng)用程序都采用該數(shù)組中的第一個(gè)地址。但是,如果返回的地址不止一個(gè),應(yīng)用程序就會(huì)相應(yīng)地選擇一個(gè)最恰當(dāng)?shù)牡刂?,而不是一直都用第一個(gè)地址。 ●?h_addr:是為了保持向后兼容而定義的字段,一般很少使用。

1.函數(shù)格式 在Winsock1中提供的gethostbyname(?)函數(shù)的格式是:

structhostentFAR*gethostbyname( constcharFAR*name );

在Winsock1中提供的異步擴(kuò)WSAAsyncGetHostByName(?)函數(shù)的格式是:

HANDLEWSAAsyncGetHostByName( HWNDhWnd, unsignedintwMsg, constcharFAR*name, charFAR*buf, intbuflen ); 2.函數(shù)參數(shù)說明

gethostbyname(?)函數(shù)中各參數(shù)的說明如下: ●?name:傳入?yún)?shù),是一個(gè)指向主機(jī)名的指針。

WSAAsyncGetHostByName(?)函數(shù)是一個(gè)Windows異步擴(kuò)展函數(shù),它在函數(shù)結(jié)束時(shí),利用Windows消息向應(yīng)用程序發(fā)出通知,其各參數(shù)的含義是: ●?hWnd:傳入?yún)?shù),??是一個(gè)窗口句柄,??表示當(dāng)異步請(qǐng)求完成時(shí),該窗口句柄應(yīng)該收到一條消息。 ●?wMsg:傳入?yún)?shù),當(dāng)異步請(qǐng)求完成時(shí),將要接收的消息。 ●?name:傳入?yún)?shù),指向主機(jī)名的指針。 ●?buf:傳出參數(shù),??接收hostent數(shù)據(jù)的數(shù)據(jù)區(qū)指針。注意該數(shù)據(jù)區(qū)必須大于hostent結(jié)構(gòu)的大小,這是因?yàn)閃indowsSockets實(shí)現(xiàn)不僅要用該數(shù)據(jù)區(qū)容納hostent結(jié)構(gòu),而且hostent結(jié)構(gòu)的成員引用的所有數(shù)據(jù)也要在該區(qū)域內(nèi)。建議用戶提供一個(gè)MAXGETHOSTSTRUCT字節(jié)大小的緩沖區(qū)。 ●?buflen:傳入?yún)?shù),上述數(shù)據(jù)區(qū)的大小。 3.函數(shù)返回信息 調(diào)用該函數(shù)時(shí)如果沒有錯(cuò)誤發(fā)生,gethostbyname(?)函數(shù)返回如上所述的一個(gè)指向hostent結(jié)構(gòu)的指針。如果調(diào)用失敗則返回一個(gè)空指針,應(yīng)用程序可以通過WSAGetLastError(?)來得到一個(gè)特定的錯(cuò)誤代碼,錯(cuò)誤代碼說明如下: ●?WSANOTINTIALISED:在應(yīng)用這個(gè)API前,必須成功調(diào)用WSAStartup(?)。 ●?WSAENETDOWN:WindowsSockets實(shí)現(xiàn)檢測(cè)到了網(wǎng)絡(luò)子系統(tǒng)的錯(cuò)誤。 ●?WSAHOST_NOT_FOUND:沒有找到授權(quán)應(yīng)答主機(jī)。 ●?WSATRY_AGAIN:沒有找到非授權(quán)主機(jī),或者服務(wù)器故障(SERVERFAIL)。 ●?WSANO_RECOVERY:無法恢復(fù)的錯(cuò)誤,如查詢有格式錯(cuò)誤(FORMERR)、拒絕服務(wù)(REFUSED)沒有通信處理機(jī)、(NOTIMP)。 ●?WSANO_DATA:有效的名字,但沒有關(guān)于請(qǐng)求類型的數(shù)據(jù)記錄。 ●?WSAEINPROGRESS:一個(gè)阻塞的WindowsSockets操作正在進(jìn)行。 ●?WSAEINTR:阻塞調(diào)用被WSACancelBlockingCall(?)取消了。

4.異步擴(kuò)展函數(shù)返回信息

WSAAsyncGetHostByName(?)函數(shù)是gethostbyname(?)函數(shù)的Windows異步擴(kuò)展函數(shù)。所謂“異步”,指的是WindowsSockets的實(shí)現(xiàn)啟動(dòng)該操作后立刻回到調(diào)用方,并傳回一個(gè)異步任務(wù)句柄,應(yīng)用程序可以用它來標(biāo)識(shí)該操作。 當(dāng)異步操作完成時(shí),如果成功則將主機(jī)名和地址信息拷貝到buf緩沖區(qū)中,同時(shí)向句柄為hWnd的應(yīng)用程序窗口發(fā)送一條消息(wMsg)。wParam參數(shù)包含了初次函數(shù)調(diào)用時(shí)返回的異步任務(wù)句柄,lParam的高16位包含著錯(cuò)誤代碼,該代碼可以是Winsock2.h中定義的任何錯(cuò)誤。錯(cuò)誤代碼為0說明異步操作成功,在成功完成的情況下,提供給初始函數(shù)調(diào)用的緩沖區(qū)中包含了一個(gè)hostent結(jié)構(gòu)。為存取該結(jié)構(gòu)中的元素,初始的緩沖區(qū)指針應(yīng)置為hostent結(jié)構(gòu)的指針。

若錯(cuò)誤代碼為WSAENOBUFS,則說明在初始調(diào)用時(shí)由buflen指出的緩沖區(qū)大小對(duì)于容納所有的結(jié)果信息來說太小了。在這種情況下,lParam的低16位提供所有信息所需的緩沖區(qū)大小。如果應(yīng)用程序認(rèn)為獲取的數(shù)據(jù)不夠,它就可以在設(shè)置了足夠容納所需信息的緩沖區(qū)(也就是大于lParam低16位提供的數(shù)值)后,重新調(diào)用WSAAsyncGetHostByName(?)函數(shù)。 錯(cuò)誤代碼和緩沖區(qū)大小應(yīng)使用WSAGETASYNCERROR和WSAGETASYNCBUFLEN宏從lParam中取出。這兩個(gè)宏的定義如下:

#defineWSAGETASYNCERROR(lParam) HIWORD(lParam) #defineWSAGETASYNCBUFLEN(lParam) LOWORD(lParam)

使用這些宏可以最大限度地提高應(yīng)用程序源代碼的可移植性。 函數(shù)的返回值指出異步操作是否成功啟動(dòng),注意它并不隱含操作本身的成功或失敗(后面要介紹的其他異步函數(shù)的返回值也與它類似)。

若操作成功啟動(dòng),則WSAAsyncGet-HostByName(?)返回一個(gè)HANDLE類型的非0值,它用來標(biāo)識(shí)該異步請(qǐng)求任務(wù)的句柄。通過該句柄使用WSACancelAsyncRequest(?)函數(shù)可取消該操作,也可通過檢查wParam消息參數(shù),以匹配異步操作和完成消息。如果異步操作不能啟動(dòng),WSAAsyncGetHostByName(?)返回一個(gè)0值,并且可使用WSAGetLastError(?)函數(shù)來獲取如下的錯(cuò)誤代碼: ●WSANOTINITIALISED:在使用本API前必須進(jìn)行一次成功的WSAStartup(?)調(diào)用。 ●?WSAENETDOWN:WindowsSockets實(shí)現(xiàn)已檢測(cè)到網(wǎng)絡(luò)子系統(tǒng)故障。 ●?WSAEINPROGRESS:一個(gè)阻塞的WindowsSockets操作正在進(jìn)行。 ●?WSAEWOULDBLOCK:本異步操作此時(shí)由于WindowsSockets實(shí)現(xiàn)的資源或其他限制的制約而無法調(diào)度。在應(yīng)用程序的窗口收到消息時(shí)可能會(huì)設(shè)置下列錯(cuò)誤代碼,它們可以通過WSAGETA-SYNCERROR宏從應(yīng)答的消息lParam中取出: ●?WSAENETDOWN:WindowsSockets實(shí)現(xiàn)已檢測(cè)到網(wǎng)絡(luò)子系統(tǒng)故障。 ●?WSAENOBUFS:可用的緩沖區(qū)空間不足或沒有。 ●?WSAHOST_NOT_FOUND:未找到授權(quán)應(yīng)答主機(jī)。 ●?WSATRY_AGAIN:未找到非授權(quán)應(yīng)答主機(jī),或SERVERFAIL。 ●?WSANO_RECOVERY:不可恢復(fù)性錯(cuò)誤。 ●?WSANO_DATA:無請(qǐng)求類型的數(shù)據(jù)記錄。 8.3.5根據(jù)主機(jī)地址取得主機(jī)信息——gethostbyaddr(?)或WSAAsyncGetHostByAddr(?)

這兩個(gè)函數(shù)可以根據(jù)主機(jī)的IP地址取得主機(jī)名和主機(jī)地址等信息。

1.函數(shù)格式 在Winsock1中提供的gethostbyaddr(?)函數(shù)的格式是:

structhostentFAR*gethostbyaddr( constcharFAR*addr, intlen, inttype );

在Winsock1中提供的異步擴(kuò)展WSAAsyncGetHostByAddr(?)函數(shù)的格式是:

HANDLEWSAAsyncGetHostByAddr( HWNDhWnd, unsignedintwMsg, constcharFAR*addr, intlen, inttype, charFAR*buf, intbuflen ); 2.函數(shù)參數(shù)說明

gethostbyaddr(?)函數(shù)的參數(shù)說明如下: ●?addr:傳入?yún)?shù),指向網(wǎng)絡(luò)字節(jié)順序地址的指針。 ●?len:傳入?yún)?shù),地址的長度,如果是IPv4類型的地址,則該值為4。 ●?type:傳入?yún)?shù),地址類型,如為AF_INET。

WSAAsyncGetHostByAddr(?)函數(shù)是gethostbyaddr(?)函數(shù)的異步版本。它的其他參數(shù)以及返回信息與WSAAsyncGetHostByName(?)函數(shù)完全相同。

3.函數(shù)返回信息 這兩個(gè)函數(shù)返回的信息與通過名稱獲取主機(jī)信息的gethostbyname(?)函數(shù)相同。

8.3.6根據(jù)協(xié)議名取得主機(jī)協(xié)議信息——getprotobyname(?)或WSAAsync-GetProtoByName(?)

函數(shù)getprotobyname()WSAAsyncGetProtoByName()可以根據(jù)協(xié)議名稱返回對(duì)應(yīng)的相關(guān)協(xié)議信息。它們都要使用到一個(gè)與協(xié)議有關(guān)的結(jié)構(gòu),該結(jié)構(gòu)的定義如下:

structprotoent{ char FAR*p_name; char FAR*FAR*p_aliases; shortp_proto; };

該結(jié)構(gòu)的成員有: ●?p_name:正式的協(xié)議名。 ●?p_aliases:它是二維字符指針,返回一個(gè)協(xié)議的所有別名。 ●?p_proto:以主機(jī)字節(jié)順序排列的協(xié)議號(hào)。 1.函數(shù)格式 在Winsock1中提供的getprotobyname(?)函數(shù)的格式是:

structprotoentFAR*getprotobyname( constcharFAR*name );

在Winsock1中提供的異步擴(kuò)展WSAAsyncGetProtoByName(?)函數(shù)的格式是:

HANDLEWSAAsyncGetProtoByName( HWNDhWnd, unsignedintwMsg, constcharFAR*name, charFAR*buf, intbuflen ); 2.函數(shù)參數(shù)說明

getprotobyname(?)函數(shù)中的參數(shù)name為傳入?yún)?shù),指向協(xié)議名的指針。 異步擴(kuò)展格式中的buf是接收protoent數(shù)據(jù)的緩沖區(qū)指針,buflen為該緩沖區(qū)的大小。其他參數(shù)與WSAAsyncGetHostByName(?)函數(shù)中的參數(shù)相同,返回信息的含義也一樣。

3.函數(shù)返回信息 如果沒有錯(cuò)誤發(fā)生,getprotobyname(?)返回如上所述的一個(gè)指向protoent結(jié)構(gòu)的指針,如果調(diào)用失敗,則返回一個(gè)空指針。應(yīng)用程序可以通過WSAGetLastError(?)來得到一個(gè)如下所示的特定錯(cuò)誤代碼: ●?WSANOTINTIALISED:在應(yīng)用這個(gè)API前,必須成功調(diào)用WSAStartup(?)。 ●?WSAENETDOWN:WindowsSockets實(shí)現(xiàn)檢測(cè)到了網(wǎng)絡(luò)子系統(tǒng)的錯(cuò)誤。 ●?WSANO_RECOVERY:無法恢復(fù)的錯(cuò)誤,如FORMERR、REFUSED、NOTIMP等。 ●?WSANO_DATA:有效的名字,但沒有關(guān)于請(qǐng)求類型的數(shù)據(jù)記錄。

●?WSAEINPROGRESS:一個(gè)阻塞的WindowsSockets操作正在進(jìn)行。 ●?WSAEINTR:阻塞調(diào)用被WSACancelBlockingCall(?)取消了。 ●?WSAHOST_NOT_FOUND:沒有找到協(xié)議。 ●?WSATRY_AGAIN:非正式的協(xié)議沒有找到或服務(wù)器失敗。 ●?WSAEFAULT:name參數(shù)不在有效的用戶地址空間。 8.3.7根據(jù)協(xié)議號(hào)取得主機(jī)協(xié)議信息——getprotobynumber(?)或WSAAsyncGetProtoByNumber(?) getprotobynumber(?)和WSAAsyncGetProtoByNumber返回對(duì)應(yīng)于給定協(xié)議號(hào)的相關(guān)協(xié)議信息。

1.函數(shù)格式 在Winsock1中提供的getprotobynumber(?)函數(shù)的格式是:

structprotoentFAR*getprotobynumber( intnumber );

在Winsock1中提供的異步擴(kuò)展WSAAsyncGetProtoByNumber(?)函數(shù)的格式是:

HANDLEWSAAsyncGetProtoByNumber( HWNDhWnd, unsignedintwMsg, intnumber, charFAR*buf, intbuflen ); 2.函數(shù)參數(shù)說明 參數(shù)number表示傳入?yún)?shù),是一個(gè)以主機(jī)字節(jié)順序排列的協(xié)議號(hào)。異步擴(kuò)展格式中的其他參數(shù)與WSAAsyncGetHostByName(?)函數(shù)中的參數(shù)含義相同。

3.函數(shù)返回信息 函數(shù)的返回信息與通過協(xié)議名獲取主機(jī)協(xié)議信息時(shí)的情況相同。 8.3.8根據(jù)服務(wù)名取得相關(guān)服務(wù)信息——?getservbyname(?)或WSAAsync-GetServByName(?) getservbyrvame(?)和WSAAsyncGetServByName(?)函數(shù)用于返回對(duì)應(yīng)于給定服務(wù)名和協(xié)議名的相關(guān)服務(wù)信息。這兩個(gè)函數(shù)都要用到一個(gè)如下所示的結(jié)構(gòu):

structservent{ charFAR*s_name; charFAR*FAR*s_aliases; shorts_port; charFAR*s_proto; };

該結(jié)構(gòu)中各成員的含義如下: ●?s_name:正規(guī)的服務(wù)名。 ●?s_aliases:所有其他的可選服務(wù)名。 ●?s_port:連接該服務(wù)時(shí)需要用到的端口號(hào),返回的端口號(hào)是以網(wǎng)絡(luò)字節(jié)順序排列的。 ●?s_proto:連接該服務(wù)時(shí)用到的協(xié)議名。 1.函數(shù)格式 在Winsock1中提供的getservbyname(?)函數(shù)的格式是:

structserventFAR*getservbyname( constcharFAR*name, constcharFAR*proto );

在Winsock1中提供的異步擴(kuò)展WSAAsyncGetServByName(?)函數(shù)的格式是: HANDLEWSAAsyncGetServByName( HWNDhWnd, unsignedintwMsg, constcharFAR*name, constcharFAR*proto, charFAR*buf, intbuflen ); 2.函數(shù)參數(shù)說明 這兩個(gè)函數(shù)中各參數(shù)的說明如下: ●?name:傳入?yún)?shù),一個(gè)指向服務(wù)名的指針。 ●proto:傳入?yún)?shù),指向協(xié)議名的指針(可選)。如果這個(gè)指針為空,getservbyname(?)返回第一個(gè)name與s_name或者某一個(gè)s_aliases匹配的服務(wù)條目。否則,getservbyname(?)對(duì)name和proto都進(jìn)行匹配。 其他參數(shù)與WSAAsyncGetHostByName(?)函數(shù)中的參數(shù)含義相同。 8.3.9根據(jù)端口號(hào)取得相關(guān)服務(wù)信息——getservbyport(?)或WSAAsync-GetServByPort(?) getservbyport(?)和WSAAsyncGetServByPort(?)函數(shù)用于返回對(duì)應(yīng)于給定端口號(hào)和協(xié)議名的相關(guān)服務(wù)信息。

1.函數(shù)格式 在Winsock1中提供的getservbyport(?)函數(shù)的格式是:

structserventFAR*getservbyport( intport, constcharFAR*proto );

在Winsock1中提供的異步擴(kuò)展WSAAsyncGetServByPort(?)函數(shù)的格式是:

HANDLEWSAAsyncGetServByPort( HWNDhWnd, unsignedintwMsg, intport, constcharFAR*proto, charFAR*buf, intbuflen ); 2.函數(shù)參數(shù)說明 這兩個(gè)函數(shù)中需要說明的參數(shù)如下: ●?port:傳入?yún)?shù),給定的端口號(hào),以網(wǎng)絡(luò)字節(jié)順序排列。 ●proto:傳入?yún)?shù),指向協(xié)議名的指針(可選)。如果這個(gè)指針為空,getservbyport(?)返回第一個(gè)port與s_port匹配的服務(wù)條目。否則,getservbyport(?)對(duì)port和proto都進(jìn)行匹配。 其他參數(shù)與WSAAsyncGetHostByName(?)函數(shù)中的參數(shù)含義相同。 8.3.10網(wǎng)絡(luò)信息獲取函數(shù)應(yīng)用實(shí)例 本小節(jié)舉一個(gè)實(shí)例來說明以上介紹的網(wǎng)絡(luò)信息獲取函數(shù)的用法。本實(shí)例只使用了三個(gè)比較典型的函數(shù),其他函數(shù)的用法與此類似。要說明的是,雖然這只是一個(gè)關(guān)于網(wǎng)絡(luò)信息獲取函數(shù)用法的實(shí)例,但該程序也是一個(gè)非常有用的實(shí)用程序,它可以獲得一臺(tái)主機(jī)的主機(jī)名、主機(jī)別名(如果有的話)、主機(jī)IP地址列表等信息。

/*************************************************************************

調(diào)試環(huán)境:VC++6.0

程序名稱:host.cpp

程序功能:該程序使用網(wǎng)絡(luò)信息獲取函數(shù)取得主機(jī)的有關(guān)信息,在程序中使用了以下三個(gè)函數(shù): gethostname(?) gethostbyname(?) getprotobyname(?)

命令格式:host**************************************************************************/ #include<winsock2.h> #include<stdio.h> #include<stdlib.h> voidmain(?) { WSADATA wsaData; int n; //存放主機(jī)名稱

char hostname[256]; //主機(jī)信息指針

hostent *pHostent; //主機(jī)協(xié)議信息指針

protoent *pProtoent; structsockaddr_in sa; if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0) { printf("FailedtoloadWinsock.\n"); return; } printf("---------------------------------------------\n");//獲得主機(jī)名

if(gethostname(hostname,sizeof(hostname))!=0){printf("gethostname(?)Error:%u\n",WSAGetLastError(?));return;} printf("以下信息由gethostname(?)函數(shù)取得\n"); printf("Localhostname:%s\n",hostname); printf("---------------------------------------------\n"); //根據(jù)主機(jī)名獲取主機(jī)信息

pHostent=gethostbyname(hostname); if(pHostent==NULL) { printf("gethostbyname(?)Error:%u\n",WSAGetLastError(?)); return; } //解析返回的hostent結(jié)構(gòu)中名稱、別名、地址類型和地址長度信息

printf("以下信息由gethostbyname(?)函數(shù)取得\n"); printf("name:%s\naliases:%s\naddrtype:%d\nlength:%d\n",pHostent->h_name, pHostent->h_aliases, pHostent->h_addrtype, pHostent->h_length); //解析hostent結(jié)構(gòu)中的主機(jī)地址

for(n=0;pHostent->h_addr_list[n];n++){memcpy(&sa.sin_addr.s_addr,pHostent->h_addr_list[n],pHostent->h_length);//輸出主機(jī)IP地址.printf("Address:%s\n",inet_ntoa(sa.sin_addr));}printf("---------------------------------------------\n");//根據(jù)協(xié)議名獲得協(xié)議信息

pProtoent=getprotobyname("tcp");if(pProtoent==NULL) {printf("getprotobyname(?)Error:%u\n",WSAGetLastError(?));return;}//解析protoent結(jié)構(gòu)中的信息

printf("以下信息由getprotobyname(?)函數(shù)取得\n");printf("name:%s\nproto:%d\n",pProtoent->p_name, pProtoent->p_proto); for(n=0;pProtoent->p_aliases[n];n++) {printf("aliases:%s\n",pProtoent->p_aliases[n]);}WSACleanup(?); }

程序的運(yùn)行結(jié)果如圖8-1所示。圖8-1網(wǎng)絡(luò)信息獲取函數(shù)使用實(shí)例程序的運(yùn)行結(jié)果8.4套接口選項(xiàng)函數(shù) 8.4.1套接口選項(xiàng)函數(shù)說明

1.函數(shù)格式 套接口選項(xiàng)獲取函數(shù)getsockopt(?)的格式如下:

intsetsockopt( SOCKETs, intlevel, intoptname, constcharFAR*optval, intoptlen );

套接口選項(xiàng)設(shè)置函數(shù)setsockopt(?)的格式如下:

intgetsockopt( SOCKETs, intlevel, intoptname, charFAR*optval, intFAR*optlen ); 2.函數(shù)參數(shù)說明

setsockopt(?)函數(shù)和getsockopt(?)函數(shù)的參數(shù)是一樣的,但 setsockopt(?)函數(shù)的optval和optlen選項(xiàng)應(yīng)該由應(yīng)用程序填寫,而getsockopt(?)函數(shù)的這兩個(gè)選項(xiàng)是返回值,由系統(tǒng)來填寫。 函數(shù)中各參數(shù)的含義如下: ●s:傳入?yún)?shù),參數(shù)s指定一個(gè)有效的套接口,我們要對(duì)這個(gè)套接口的選項(xiàng)進(jìn)行操作。 ●?level:傳入?yún)?shù),套接口選項(xiàng)定義的級(jí)別(層次)。常用的級(jí)別有SOL_SOCKET、IPPROTO_IP和IPPROTO_TCP,在8.4.2~8.4.4節(jié)將對(duì)這些級(jí)別對(duì)應(yīng)的選項(xiàng)進(jìn)行專門介紹。 ●?optname:傳入?yún)?shù),需設(shè)置或獲取的套接口選項(xiàng),這些選項(xiàng)的名稱均是在Winsock頭文件內(nèi)定義的常數(shù)值。 ●?optval:對(duì)于setsockopt(?)函數(shù)來說,?它是傳入?yún)?shù);對(duì)于getsockopt(?)函數(shù)來說,它是傳出參數(shù)。該參數(shù)是指向存放選項(xiàng)值緩沖區(qū)的指針。 ●?optlen:對(duì)于setsockopt(?)函數(shù)來說,?它是傳入?yún)?shù);對(duì)于getsockopt(?)函數(shù)來說,它既是傳出參數(shù)也是傳入?yún)?shù)。該參數(shù)是指向optval緩沖區(qū)長度(或套接口選項(xiàng)變量的長度)的指針。 3.函數(shù)返回信息 若函數(shù)調(diào)用時(shí)無錯(cuò)誤發(fā)生,則setsockopt(?)函數(shù)和getsockopt(?)函數(shù)都返回0。如果調(diào)用發(fā)生錯(cuò)誤,則返回SOCKET_ERROR錯(cuò)誤信息,應(yīng)用程序可通過WSAGetLastError(?)函數(shù)獲取對(duì)錯(cuò)誤信息的進(jìn)一步說明。以下是錯(cuò)誤代碼的含義說明: ●?WSANOTINITIALISED:在使用此API之前應(yīng)成功調(diào)用WSAStartup(?)。 ●?WSAENETDOWN:Windows套接口實(shí)現(xiàn)已檢測(cè)到網(wǎng)絡(luò)子系統(tǒng)失效。 ●?WSAEFAULT:setsockopt(?)函數(shù)返回時(shí),表示optval不是進(jìn)程地址空間中的一個(gè)有效部分;getsockopt(?)函數(shù)返回時(shí),表示optlen參數(shù)非法。 ●?WSAEINPROGRESS:一個(gè)阻塞的Windows套接口調(diào)用正在運(yùn)行中。 ●?WSAEINVAL:level值非法,或optval中的信息非法。 ●?WSAENETRESET:當(dāng)SO_KEEPALIVE設(shè)置后連接超時(shí)。 ●?WSAENOPROTOOPT:未知或不支持選項(xiàng)。其中,SOCK_STREAM類型的套接口不支持SO_BROADCAST選項(xiàng),SOCK_DGRAM類型的套接口不支持SO_DONTLINGER、SO_KEEPALIVE、SO_LINGER和SO_OOBINLINE選項(xiàng)。 ●?WSAENOTCONN:當(dāng)設(shè)置SO_KEEPALIVE后連接被復(fù)位。 ●?WSAENOTSOCK:描述字不是一個(gè)套接口。 8.4.2SOL_SOCKET選項(xiàng)級(jí)別

SOL_SOCKET選項(xiàng)級(jí)別主要針對(duì)傳輸層協(xié)議(TCP或UDP)。在SOL_SOCKET選項(xiàng)級(jí)別下,套接口的選項(xiàng)有兩種類型:一種是值為布爾型(BOOL)的選項(xiàng),這種選項(xiàng)可以允許或禁止一種特性;另一種是值為整型(int)或結(jié)構(gòu)型(StructLinger)的選項(xiàng),這種選項(xiàng)可以用來設(shè)置系統(tǒng)工作時(shí)的某些參數(shù)。

允許一個(gè)布爾型選項(xiàng),則將optval指向一個(gè)非零的整型數(shù);禁止一個(gè)布爾型選項(xiàng),則可以將optval指向一個(gè)等于零的整型數(shù)。對(duì)于布爾型選項(xiàng),optlen應(yīng)等于sizeof(int)。對(duì)于非布爾型的其他選項(xiàng),optval應(yīng)該指向包含所需選項(xiàng)的整型量或結(jié)構(gòu)量,而optlen則為整形量或結(jié)構(gòu)量的長度。 還要注意一個(gè)問題,套接口的有些屬性值既可以設(shè)置(即可以使用setsockopt(?)函數(shù)),也可以獲取(即使用getsockopt(?)函數(shù)),但有些套接口屬性只能獲取或只能設(shè)置。 后面要介紹的其他兩種選項(xiàng)級(jí)別(IPPROTO_IP和IPPROTO_TCP)與SOL_SOCKET選項(xiàng)級(jí)別的情況類似。 表8-1所示為在SOL_SOCKET選項(xiàng)級(jí)別下的各種選項(xiàng)。表8-1SOL_SOCKET選項(xiàng)級(jí)別下的各選項(xiàng) (1)?SO_ACCEPTCONN:該選項(xiàng)只能獲取。如果已通過listen(?)函數(shù)調(diào)用,??套接口將進(jìn)入監(jiān)聽模式,這時(shí)獲取這個(gè)選項(xiàng)時(shí)就會(huì)返回TRUE。數(shù)據(jù)報(bào)類型的套接口(SOCK_DGRAM)不支持這一選項(xiàng)。

(2)?SO_BROADCAST:??該選項(xiàng)可以獲取也可以設(shè)置。如果指定的套接口該選項(xiàng)已經(jīng)設(shè)置為TRUE,則允許套接口廣播收發(fā)信息。該選項(xiàng)只有對(duì)非SOCK_STREAM類型的所有套接口才是有效的。

廣播是一種特殊的數(shù)據(jù)發(fā)送方法,使本地子網(wǎng)上的所有機(jī)器都能收到相同的數(shù)據(jù)。廣播通信的缺點(diǎn)在于假如同時(shí)有許多進(jìn)程發(fā)送廣播數(shù)據(jù),網(wǎng)絡(luò)立刻就會(huì)擁擠不堪,造成網(wǎng)絡(luò)性能大大降低,甚至有可能陷入癱瘓。要想接收一條廣播消息,首先必須啟用廣播選項(xiàng),然后使用某個(gè)數(shù)據(jù)報(bào)接收函數(shù),比如recvfrom(?)或WSARecvFrom(?)。該選項(xiàng)的設(shè)置方法如下: …… BOOLbBroadcast=TRUE; //創(chuàng)建一個(gè)數(shù)據(jù)報(bào)套接口

s=socket(AF_INET,SOCK_DGRAM,0); …… //設(shè)置廣播選項(xiàng)

if(setsocketopt(s,SOL_SOCKET,SO_BROADCAST,(char*)&bBroadcast,sizeof(BOOL))==SOCKET_ERROR) { printf(''setsocketopt(?)Error:u%\n'',WSAGetLastError(?)); return; } …… (3)?SO_CONNECT_TIME:該選項(xiàng)只能獲取。它是一個(gè)微軟Windows操作系統(tǒng)專用選項(xiàng),用于返回連接建立的時(shí)間,以秒為單位。該選項(xiàng)可以在客戶端的SOCKET句柄上調(diào)用,以判斷連接是否已經(jīng)建立,以及建立了多長時(shí)間。若套接口當(dāng)前尚未建立連接,返回值便是0xFFFFFFFF。

(4)?SO_DEBUG:該選項(xiàng)值可以獲取,也可以設(shè)置。在應(yīng)用程序設(shè)置了SO_DEBUG選項(xiàng)的情況下,系統(tǒng)將記錄調(diào)試信息。至于調(diào)試信息如何展示,要取決于服務(wù)提供者的基層實(shí)施方式。要想打開調(diào)試信息,可調(diào)用setsockopt(?)函數(shù)設(shè)置SO_DEBUG為TRUE。若用SO_DEBUG選項(xiàng)調(diào)用getsockopt(?)函數(shù),會(huì)返回TRUE或FALSE,分別代表允許和禁止記錄調(diào)試信息。但目前尚無任何一種Win32平臺(tái)支持的SO_DEBUG選項(xiàng)。 (5)?SO_LINGER:該選項(xiàng)值可以獲取,也可以設(shè)置。該選項(xiàng)不能使用在SOCK_DGRAM類型的套接口上。它用于控制在closesocket(?)函數(shù)已執(zhí)行的情況下,如何處理套接口數(shù)據(jù)排列上未發(fā)送完畢的數(shù)據(jù)。該選項(xiàng)要通過linger結(jié)構(gòu)來設(shè)置,該結(jié)構(gòu)的定義如下:

structlinger{ intl_onoff; intl_linger; };

l_onoff字段用來控制SO_LINGER選項(xiàng)的打開或關(guān)閉,為了使該選項(xiàng)起作用,該字段應(yīng)該設(shè)置為一個(gè)非0的值。l_linger字段表示延遲時(shí)間,以秒為單位。 當(dāng)l_onoff和l_linger字段取不同的值時(shí),系統(tǒng)的操作方式也不同,它們的取值情況如表8-2所示。表8-2SO_LINGER選項(xiàng)取值情況說明 (6)?SO_DONTLINGER:該選項(xiàng)值可以獲取,也可以設(shè)置。若在一個(gè)流類套接口上設(shè)置了SO_DONTLINGER選項(xiàng),也就是說將linger結(jié)構(gòu)的l_onoff域設(shè)為0,則closesocket(?)調(diào)用立即返回,但是,如果可能,排隊(duì)的數(shù)據(jù)將在套接口關(guān)閉之前被發(fā)送。SO_DONTLINGER和SO_LINGER選項(xiàng)將直接影響使用closesocket(?)函數(shù)關(guān)閉一個(gè)套接口時(shí)系統(tǒng)對(duì)套接口的操作行為。表8-3總結(jié)了這兩個(gè)選項(xiàng)對(duì)套接口關(guān)閉方式的影響。表8-3SO_DONTLINGER和SO_LINGER選項(xiàng)對(duì)套接口關(guān)閉方式的影響 (7)?SO_DONTROUTE:該選項(xiàng)可以獲取,也可以設(shè)置。

(8)?SO_ERROR:該選項(xiàng)只能獲取,用于返回以具體套接口為基礎(chǔ)的錯(cuò)誤代碼,在返回后系統(tǒng)一般將該選項(xiàng)設(shè)置為0。

(9)?SO_KEEPALIVE:該選項(xiàng)可以獲取,也可以設(shè)置,它只適用于以TCP為基礎(chǔ)的套接口。在Windows95及Windows98操作系統(tǒng)中,這兩個(gè)鍵都位于下述注冊(cè)表路徑中:\HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\VxD\MSTCP

而在WindowsNT和Windows2000中,這兩個(gè)鍵位于下述位置:

\HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\TCPIP\Parameters服務(wù)器(例如FTP服務(wù)器)一般要設(shè)置該選項(xiàng),這樣當(dāng)客戶在非正常終止連接的情況下,經(jīng)過一段時(shí)間后,服務(wù)器也能終止該連接。

(10)?SO_MAX_MSG_SIZE:該選項(xiàng)只能獲取。

(11)?SO_OOBINLINE:該選項(xiàng)可以獲取,也可以設(shè)置。 (12)?SO_PROTOCOL_INFO:該選項(xiàng)只能獲取,獲取WSAPROTCOL_INFO結(jié)構(gòu)中與套接口關(guān)聯(lián)在一起的協(xié)議特征信息。該選項(xiàng)由Winsock2支持。

(13)?SO_RCVBUF:該選項(xiàng)可以獲取,也可以設(shè)置。

(14)?SO_SNDBUF:該選項(xiàng)可以獲取,也可以設(shè)置。與SO_RCVBUF選項(xiàng)相對(duì)應(yīng),該選項(xiàng)用于確定發(fā)送緩沖區(qū)的大小。

(15)?SO_TYPE:該選項(xiàng)只能獲取,??用于返回指定套接口的類型??赡艿奶捉涌陬愋桶⊿OCK_DGRAM、SOCK_STREAM和SOCK_RAW。

(16)?SO_SNDTIMEO:該選項(xiàng)可以獲取,也可以設(shè)置。 (17)?SO_RCVTIMEO:該選項(xiàng)可以獲取,也可以設(shè)置。

(18)?SO_REUSEADDR:該選項(xiàng)可以獲取,也可以設(shè)置,表示該套接口能和一個(gè)已在使用中的地址捆綁。

(19)?SO_EXCLUSIVEADDRUSE:該選項(xiàng)可以獲取,也可以設(shè)置。該選項(xiàng)的作用是禁止其他進(jìn)程在一個(gè)本地地址上使用SO_REUSEADDR(重復(fù)使用地址)。 8.4.3IPPROTO_IP選項(xiàng)級(jí)別 該選項(xiàng)級(jí)別包括的主要選項(xiàng)如表8-4所示。表8-4IPPROTO_IP級(jí)別套接口選項(xiàng) (1)?IP_OPTIONS:該選項(xiàng)可以獲取,也可以設(shè)置。它是專門針對(duì)IP數(shù)據(jù)報(bào)選項(xiàng)字段的,通過該選項(xiàng)字段,用戶可以獲取IP數(shù)據(jù)報(bào)頭選項(xiàng)字的設(shè)置情況,也可以對(duì)IP選項(xiàng)字段進(jìn)行設(shè)置。IP數(shù)據(jù)報(bào)選項(xiàng)的格式如圖2-12所示。 ●記錄路由:IP數(shù)據(jù)報(bào)在傳輸過程中,每經(jīng)過一個(gè)路由器,路由器就將自己的IP地址添加到IP數(shù)據(jù)報(bào)頭內(nèi)的選項(xiàng)字段位置。 ●記錄時(shí)間戳:IP數(shù)據(jù)報(bào)在傳輸過程中,每經(jīng)過一個(gè)路由器,路由器就將自己的IP地址及時(shí)間添加到IP數(shù)據(jù)報(bào)頭內(nèi)的選項(xiàng)字段位置。 ●寬松源路由選擇:IP數(shù)據(jù)報(bào)在傳輸過程中,要經(jīng)過IP數(shù)據(jù)報(bào)選項(xiàng)內(nèi)列出的每個(gè)IP地址,但也可以經(jīng)過其他的IP地址。 ●嚴(yán)格源路由選擇:IP數(shù)據(jù)報(bào)在傳輸過程中,只能經(jīng)過IP數(shù)據(jù)報(bào)選項(xiàng)內(nèi)列出的每個(gè)IP地址。 下面我們以記錄路由為例說明如何進(jìn)行IP_OPTIONS選項(xiàng)的設(shè)置。 第一步:先聲明一個(gè)數(shù)據(jù)結(jié)構(gòu),它包括選項(xiàng)碼、選項(xiàng)長度、偏移量與選項(xiàng)數(shù)據(jù)4個(gè)字段。要注意的是,由于IP選項(xiàng)最長為40字節(jié),所以所定義的結(jié)構(gòu)長度不能超過這個(gè)數(shù)值。

第二步:根據(jù)要設(shè)置的選項(xiàng),對(duì)說明的選項(xiàng)數(shù)據(jù)結(jié)構(gòu)各字段進(jìn)行初始化。選項(xiàng)碼字段的值見2.3.3小節(jié)。 第三步:使用setsockopt(?)函數(shù)對(duì)IP_OPTIONS選項(xiàng)進(jìn)行設(shè)置。 以上三步對(duì)應(yīng)的代碼如下:

//定義一個(gè)數(shù)據(jù)結(jié)構(gòu)

structip_oprion_hdr { unsignedchar code; unsignedchar length; unsignedchar offset; unsignedlong addrs[9]; }opthdr; …… //對(duì)定義的結(jié)構(gòu)進(jìn)行初始化

byzero((char*)&opthdr,sizeof(opthdr)); //記錄路由選項(xiàng)碼

opthdr.code=0x87; //總的選項(xiàng)長度

opthdr.length=39; //選項(xiàng)數(shù)據(jù)的初始位置

opthdr.offset=4; //設(shè)置記錄路由選項(xiàng)

ret=setsockopt(s,IPPROTO_IP,IP_OPTIONS,(char*)&opthdr,sizeof(opthdr)); …… (2)?IP_HDRINCL:該選項(xiàng)可以獲取,也可以設(shè)置。

(3)?IP_TOS:該選項(xiàng)可以獲取,也可以設(shè)置。

(4)?IP_TTL:該選項(xiàng)可以獲取,也可以設(shè)置。

(5)?IP_MULTICAST_TTL:該選項(xiàng)可以獲取,也可以設(shè)置。

(6)?IP_MULTICAST_IF:該選項(xiàng)可以獲取,也可以設(shè)置,用于為IP多播設(shè)置一個(gè)本地接口,本地機(jī)器以后發(fā)出的任何多播數(shù)據(jù)都會(huì)經(jīng)由該接口傳送出去。 (7)?IP_MULTICAST_LOOP:該選項(xiàng)可以獲取,也可以設(shè)置。該選項(xiàng)用于控制發(fā)送的多播數(shù)據(jù)是否進(jìn)入本地套接口的輸入數(shù)據(jù)隊(duì)列中。

(8)?IP_ADD_MEMBERSHIP:該選項(xiàng)只能設(shè)置。該選項(xiàng)實(shí)際是由Winsock1提供的一個(gè)方法,可將一個(gè)套接口加入一個(gè)指定的IP多播組,此時(shí)需要用socket函數(shù)來創(chuàng)建地址族為AF_INET的一個(gè)套接口,同時(shí)將套接口的類型設(shè)為SOCK_DGRAM。要想將套接口加入一個(gè)多播組,要使用如下結(jié)構(gòu):

srtuctip_mreq{ structin_addr imr_multiaddr; structin_addr imr_interface; }; 在ip_mreq結(jié)構(gòu)中,imr_multiaddr對(duì)應(yīng)于套接口將要加入的那個(gè)多播組的二進(jìn)制格式地址;而imr_interface對(duì)應(yīng)于將要用來收發(fā)多播數(shù)據(jù)的一個(gè)本地接口。 (9)IP_DROP_MEMBERSHIP:該選項(xiàng)只能設(shè)置,用于將套接口從指定的IP組內(nèi)刪去,即撤銷其成員資格。該選項(xiàng)正好與IP_ADD_MEMBERSHIP相反。使用ip_mreq結(jié)構(gòu)調(diào)用該選項(xiàng),并在該結(jié)構(gòu)中放入與當(dāng)初加入指定多播組時(shí)相同的值,套接口便會(huì)從那個(gè)組內(nèi)刪去,脫離成員關(guān)系。

(10)?IP_DONTFRAGMENT:該選項(xiàng)可以獲取,也可以設(shè)置,用來控制是否對(duì)IP數(shù)據(jù)報(bào)進(jìn)行分段。如果設(shè)置為TRUE,IP數(shù)據(jù)報(bào)在傳輸過程中就不需要對(duì)IP數(shù)據(jù)報(bào)進(jìn)行分段處理,當(dāng)然這樣就存在一個(gè)問題,當(dāng)一個(gè)IP數(shù)據(jù)報(bào)的大小已經(jīng)超過了最大數(shù)據(jù)傳輸單元(MTU)的值時(shí),這個(gè)數(shù)據(jù)報(bào)就會(huì)被丟棄,同時(shí)向發(fā)送者返回一條ICMP錯(cuò)誤消息,提示用戶數(shù)據(jù)需要分段,但未設(shè)置分段標(biāo)志位。 8.4.4IPPROTO_TCP選項(xiàng)級(jí)別 該選項(xiàng)是針對(duì)TCP協(xié)議的。在Winsock中僅有一個(gè)IPPROTO_TCP級(jí)別的選項(xiàng),即TCP_NODELAY選項(xiàng),該選項(xiàng)用來打開或關(guān)閉Nagle算法。如果該選項(xiàng)的值為TRUE,則在對(duì)應(yīng)的套接口上禁止使用Nagle算法。在系統(tǒng)默認(rèn)情況下,Nagle算法是打開的,該選項(xiàng)只適用于流式套接口(SOCK_STREAM),其地址族為AF_INET。這個(gè)選項(xiàng)可用在所有Winsock版本上,并得到了所有Win32平臺(tái)的支持。

Nagle算法將未確認(rèn)的數(shù)據(jù)存入緩沖區(qū),直到蓄足一個(gè)包后一起發(fā)送,這樣做的好處是可以減少主機(jī)發(fā)送的零碎小數(shù)據(jù)包的數(shù)目,以減少網(wǎng)絡(luò)通信的開銷,提高系統(tǒng)的吞吐量。但對(duì)于某些應(yīng)用來說,這種算法將降低系統(tǒng)性能,例如交互性較強(qiáng)的Telnet應(yīng)用程序,用戶可通過它登錄至一臺(tái)遠(yuǎn)程機(jī)器,然后向其傳送命令。通常,用戶每秒只會(huì)進(jìn)行少量的鍵擊,若使用Nagle算法,便會(huì)造成響應(yīng)的遲鈍,甚至造成對(duì)方主機(jī)不予應(yīng)答的錯(cuò)覺。此時(shí),使用TCP_NODELAY選項(xiàng)可將此算法關(guān)閉,以適應(yīng)一些交互性較強(qiáng)的應(yīng)用程序。應(yīng)用程序編寫者只有在確切了解它的效果并在確實(shí)需要的情況下,才可設(shè)置TCP_NODELAY選項(xiàng),因?yàn)樵谝话愕膽?yīng)用中如果設(shè)置該選項(xiàng),則對(duì)網(wǎng)絡(luò)性能有明顯的負(fù)面影響。 8.4.5套接口屬性設(shè)置和獲取實(shí)例 在本實(shí)例程序中,使用getsockopt(?)函數(shù)來獲取套接口的類型、接收緩沖和發(fā)送緩沖的大小,然后使用setsockopt(?)函數(shù)對(duì)套接口接收緩沖進(jìn)行重新設(shè)置,并用getsockopt(?)函數(shù)獲取重新設(shè)置以后的大小。實(shí)例程序如下:

/*************************************************************************

調(diào)試環(huán)境:VC++6.0

程序名稱:socketopt.cpp

程序功能:該程序演示了getsockopt(?)函數(shù)和setsockopt(?) 函數(shù)在程序中的用法 命令格式:socketopt **************************************************************************/#include<winsock2.h>#include<stdio.h>#include<stdlib.h>voidmain(?){ WSADATAwsaData; SOCKETs; //存放選項(xiàng)值

intoptname; //選項(xiàng)的長度

intoptlen;if(WSAStartup(MA

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論