




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
第8章WinsockAPI8.1字節(jié)排序函數(shù)8.2IP地址轉(zhuǎn)換函數(shù)8.3網(wǎng)絡(luò)信息獲取函數(shù)(數(shù)據(jù)庫函數(shù))8.4套接口選項函數(shù)8.5套接口I/O處理函數(shù)8.6事件對象I/O管理8.7錯誤處理函數(shù)8.8Winsock2支持的其他函數(shù)習題8.1字節(jié)排序函數(shù) 8.1.14字節(jié)主機字節(jié)順序的數(shù)轉(zhuǎn)化為網(wǎng)絡(luò)字節(jié)順序——htonl(?)和WSAHtonl(?) 1.函數(shù)格式 在Winsock1中提供的htonl(?)函數(shù)的格式是:u_longhtonl( u_longhostlong);
在Winsock2中提供的WSAHtonl(?)函數(shù)的擴展格式是:intWSAHtonl( SOCKETs, u_longhostlong, u_longFAR*lpnetlong ); 2.函數(shù)參數(shù)說明 這兩個函數(shù)中各參數(shù)的說明如下: ●?hostlong:傳入?yún)?shù),它是一個用主機字節(jié)順序表示的將要被轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)順序的32位數(shù)(即4個字節(jié)的數(shù)),u_long表示無符號長整型數(shù)。 ●?s:傳入?yún)?shù),在Winsock2提供的擴展格式中增加了標識套接口的描述字。 ●?lpnetlong:傳出參數(shù),一個指向32位的網(wǎng)絡(luò)字節(jié)順序數(shù)的指針。 3.函數(shù)返回信息 這兩個函數(shù)的返回值差別較大,在使用時一定要注意。 對于htonl(?)函數(shù)來說,如果該函數(shù)被調(diào)用時正確執(zhí)行,則這個函數(shù)返回一個32位的TCP/IP網(wǎng)絡(luò)字節(jié)順序的數(shù)。 對于WSAHtonl(?)函數(shù)來說,如果該函數(shù)被調(diào)用時正確執(zhí)行,則這個函數(shù)的返回值為0,函數(shù)返回的32位網(wǎng)絡(luò)字節(jié)順序的數(shù)據(jù)是指針參數(shù)lpnetlong所指向的數(shù)。如果在調(diào)用時該函數(shù)發(fā)生錯誤,則返回SOCKET_ERROR錯誤信息,可以進一步使用WSAGetLastError(?)函數(shù)取得對該錯誤的具體描述。錯誤代碼如下: ●?WSANOTINITIALISED:在調(diào)用本API之前應(yīng)成功調(diào)用WSAStartup(?)。 ●?WSAENETDOWN:網(wǎng)絡(luò)子系統(tǒng)失效。 ●?WSAENOTSOCK:描述字不是一個套接口。 ●?WSAEFAULT:指針參數(shù)lpnetlong不在有效的用戶地址空間中。
4.函數(shù)使用說明 該函數(shù)的使用比較簡單,主要用來將一個32位的IP地址從主機字節(jié)順序轉(zhuǎn)化為網(wǎng)絡(luò)字節(jié)順序,具體用法可以參考第7章的網(wǎng)絡(luò)程序?qū)嵗?8.1.22字節(jié)主機字節(jié)順序的數(shù)轉(zhuǎn)化為網(wǎng)絡(luò)字節(jié)順序——htons(?)和WSAHtons(?) 1.函數(shù)格式在Winsock1中提供的htons(?)函數(shù)的格式是:
u_shorthtons(u_shorthostshort);
在Winsock2中提供的WSAHtons(?)函數(shù)的擴展格式是:
u_shortWSAHtons(SOCKETs,u_shorthostshort,u_shortFAR*lpnetshort); 2.函數(shù)參數(shù)說明 這兩個函數(shù)中各參數(shù)的說明如下: ●?hostshort:傳入?yún)?shù),它是一個以主機字節(jié)順序表示的將要被轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)順序的16位數(shù)(即2字節(jié)數(shù)),u_short表示無符號短整型數(shù)。 ●?s:傳入?yún)?shù),Winsock2提供的擴展格式中增加的標識套接口的描述字。 ●?lpnetshort:傳出參數(shù),一個指向16位網(wǎng)絡(luò)字節(jié)順序數(shù)的指針。 3.函數(shù)返回信息
htons(?)函數(shù)如果被調(diào)用時正確執(zhí)行,則這個函數(shù)返回一個16位TCP/IP網(wǎng)絡(luò)字節(jié)順序的數(shù)。
WSAHtons(?)函數(shù)如果被調(diào)用時正確執(zhí)行,則這個函數(shù)返回0,函數(shù)返回的16位網(wǎng)絡(luò)字節(jié)順序的數(shù)據(jù)是指針參數(shù)lpnetshort所指向的數(shù)。如果在調(diào)用時該函數(shù)發(fā)生錯誤,則返回SOCKET_ERROR錯誤信息,可以進一步使用WSAGetLastError(?)函數(shù)取得對該錯誤的具體描述。錯誤代碼與WSAHtonl(?)函數(shù)的錯誤代碼類似。
4.函數(shù)使用說明 該函數(shù)一般用來將一個16位的TCP或UDP端口號從主機字節(jié)順序轉(zhuǎn)化為網(wǎng)絡(luò)字節(jié)順序,用法可以參考第7章的程序?qū)嵗?8.1.34字節(jié)網(wǎng)絡(luò)字節(jié)順序的數(shù)轉(zhuǎn)化為主機字節(jié)順序——ntohl(?)和WSANtohl(?) 1.函數(shù)格式 在Winsock1中提供的ntohl(?)函數(shù)的格式是:
u_longntohl( u_longnetlong );
在Winsock2中提供的WSANtohl(?)函數(shù)的擴展格式是:
u_longWSANtohl( SOCKETs, u_longnetlong, u_longFAR*lphostlong ); 2.函數(shù)參數(shù)說明 這兩個函數(shù)的參數(shù)說明如下: ●?netlong:傳入?yún)?shù),一個以網(wǎng)絡(luò)字節(jié)順序表示的32位數(shù)。 ●?s:傳入?yún)?shù),在Winsock2中提供的擴充格式中增加的標識套接口的描述字。 ●?lphostlong:傳出參數(shù),指向一個32位主機字節(jié)順序數(shù)的指針。
3.函數(shù)返回信息
ntohl(?)函數(shù)在調(diào)用成功后,返回一個主機字節(jié)順序的32位數(shù)。 WSANtohl(?)函數(shù)在調(diào)用正確時返回0,函數(shù)返回的32位主機字節(jié)順序的數(shù)據(jù)是指針參數(shù)lphostlong所指向的數(shù)。如果調(diào)用錯誤,則返回錯誤信息SOCKET_ERROR,可以進一步使用WSAGetLastError(?)函數(shù)取得對該錯誤的具體描述。具體錯誤代碼與WSAHtonl(?)函數(shù)的錯誤代碼類似。
4.函數(shù)使用說明 該函數(shù)常用來將一個網(wǎng)絡(luò)字節(jié)順序表示的32位IP地址轉(zhuǎn)化為主機字節(jié)順序。 8.1.42字節(jié)網(wǎng)絡(luò)字節(jié)順序的數(shù)轉(zhuǎn)化為主機字節(jié)順序——ntohs(?)和WSANtohs(?) 1.函數(shù)格式 在Winsock1中提供的ntohs(?)函數(shù)的格式是:
u_shortntohs( u_shortnetshort );
在Winsock2中提供的WSANtohs(?)函數(shù)的擴展格式是:
u_shortWSANtohs( SOCKETs, u_shortnetshort, u_shortFAR*lphostshort ); 2.函數(shù)參數(shù)說明 這兩個函數(shù)的參數(shù)說明如下: ●?netshort:傳入?yún)?shù),一個以網(wǎng)絡(luò)字節(jié)順序表示的16位數(shù)。 ●?s:傳入?yún)?shù),在Winsock2提供的擴充格式中增加的一個標識套接口的描述字。 ●?lphostshort:傳出參數(shù),指向一個16位主機字節(jié)順序數(shù)的指針。 3.函數(shù)返回信息
ntohs(?)函數(shù)在調(diào)用成功后,返回一個主機字節(jié)順序的16位數(shù)。
WSANtohs(?)函數(shù)在調(diào)用正確時返回0,函數(shù)返回的16位主機字節(jié)順序的數(shù)據(jù)是指針參數(shù)lphostshort所指向的數(shù)。如果調(diào)用錯誤,則返回錯誤信息SOCKET_ERROR,可以進一步使用WSAGetLastError(?)函數(shù)取得對該錯誤的具體描述。具體錯誤代碼與WSAHtonl(?)函數(shù)的錯誤代碼類似。
4.函數(shù)使用說明 該函數(shù)常用來將一個網(wǎng)絡(luò)字節(jié)順序表示的16位TCP或UDP端口號轉(zhuǎn)化為主機字節(jié)順序。8.2IP地址轉(zhuǎn)換函數(shù) 8.2.1點分十進制數(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ù),是一個以“.”間隔的字符串,即一個點分十進制數(shù)表示的IP地址。
3.函數(shù)返回信息 該函數(shù)調(diào)用成功后,返回一個無符號長整型數(shù)(UnsignedLong),它是以網(wǎng)絡(luò)字節(jié)順序表示的32位二進制IP地址。如果傳入的字符串不是一個合法的Internet地址,如當“a.b.c.d”地址中任一項超過255時,則inet_addr(?)返回INADDR_NONE提示信息。 4.函數(shù)使用說明 當IP地址用點分十進制數(shù)表示時,即4個字節(jié)的數(shù)以“.”間隔,則用這種格式書寫的IP地址可有下列4種表示方式。
(1)?a.b.c.d:當四個部分都有固定的值時,則每一個部分被解釋成一個字節(jié)的數(shù)據(jù),從左到右組成Internet4字節(jié)地址。請注意,當一個Internet地址在Intel機器上表示成一個32位整型數(shù)時,則上述數(shù)據(jù)在計算機內(nèi)部的表示為“d.c.b.a”。這是因為在Intel處理器內(nèi)部,字中的字節(jié)是按由低到高的順序存儲的,即“小序在前”。 (2)a.b.c:對于一個只有三個部分組成的IP地址,最后一部分被解釋成16位數(shù)據(jù),并作為網(wǎng)絡(luò)地址最右邊的兩個字節(jié)。
(3)a.b:對于一個只有兩個部分組成的IP地址,最后一部分解釋成24位數(shù)據(jù),并作為網(wǎng)絡(luò)地址最右邊的三個字節(jié)。
(4)a:對于一個僅有一個部分的IP地址,將它的值直接存入網(wǎng)絡(luò)地址而不做任何字節(jié)重組。 該函數(shù)的用法見第7章中的客戶程序?qū)嵗?8.2.2網(wǎng)絡(luò)字節(jié)順序的IP地址轉(zhuǎn)換為點分十進制數(shù)表示的IP地址——inet_ntoa(?) 1.函數(shù)格式
inet_ntoa(?)函數(shù)的格式如下:
char*inet_ntoa( structin_addrin ); 2.函數(shù)參數(shù)說明 該函數(shù)中的參數(shù)in為傳入?yún)?shù),表示一個結(jié)構(gòu)型的IP主機地址。 3.函數(shù)返回信息 該函數(shù)調(diào)用成功后,返回一個指向字符的指針,該指針指向一個文本型的緩沖區(qū),緩沖區(qū)中存有用點分十進制形式表示的IP地址。如果函數(shù)調(diào)用失敗的話,則返回一個空指針(NULL)。
4.函數(shù)使用說明 該函數(shù)的用法參見第7章中的服務(wù)器程序?qū)嵗?.3網(wǎng)絡(luò)信息獲取函數(shù)(數(shù)據(jù)庫函數(shù)) 8.3.1獲得主機名——gethostname(?) gethostname(?)函數(shù)用來取得一臺主機的名稱信息。
1.函數(shù)格式 該函數(shù)的格式如下:
intgethostname( charFAR*name, intnamelen ); 2.函數(shù)參數(shù)說明
gethostname(?)函數(shù)中各參數(shù)的說明如下: ●?name:傳出參數(shù),一個指向?qū)⒁娣胖鳈C名的緩沖區(qū)指針,當函數(shù)調(diào)用完成時,主機名被存入該緩沖區(qū)中。 ●?namelen:傳入?yún)?shù),緩沖區(qū)的長度。
3.函數(shù)返回信息 如果函數(shù)調(diào)用時沒有發(fā)生錯誤,則gethostname(?)函數(shù)返回0。如果函數(shù)調(diào)用失敗,則返回SOCKET_ERROR錯誤信息。應(yīng)用程序可以通過WSAGetLastError(?)來得到一個特定的錯誤代碼,錯誤代碼說明如下:
●?WSAEFAULT:名字長度參數(shù)太小。 ●?WSANOTINTIALISED:在應(yīng)用這個API前,必須成功調(diào)用WSAStartup(?)。 ●?WSAENETDOWN:WindowsSockets實現(xiàn)檢測到了網(wǎng)絡(luò)子系統(tǒng)的錯誤。 ●?WSAEINPROGRESS:一個阻塞的WindowsSockets操作正在進行。
4.函數(shù)使用說明 該函數(shù)把本地主機名存放入由name參數(shù)指定的緩沖區(qū)中。主機名的形式取決于WindowsSockets系統(tǒng)的實現(xiàn),它可能是一個簡單的主機名,或者是一個域名。不管是哪種形式,該函數(shù)返回的名字必定可以在gethostbyname(?)和WSAAsyncGetHostByName(?)函數(shù)中使用。 8.3.2獲得與套接口相連的遠程協(xié)議地址——getpeername(?) 1.函數(shù)格式
getpeername(?)函數(shù)的格式如下:
intgetpeername( SOCKETs, structsockaddrFAR*name, intFAR*namelen ); 2.函數(shù)參數(shù)說明 該函數(shù)中各參數(shù)的說明如下: ●?s:傳入?yún)?shù),一個已建立連接的套接口描述字。 ●?name:傳出參數(shù),指向返回的遠程協(xié)議地址。 ●?namelen:傳出參數(shù),遠程協(xié)議地址長度。
3.函數(shù)返回信息 調(diào)用該函數(shù)時若無錯誤發(fā)生,則getpeername(?)函數(shù)返回0。如果調(diào)用失敗,則返回SOCKET_ERROR錯誤信息,應(yīng)用程序可通過調(diào)用WSAGetLastError(?)函數(shù)來獲取對該錯誤的進一步描述。可獲得的錯誤代碼如下: ●?WSANOTINITIALISED:在使用此API之前應(yīng)成功調(diào)用WSAStartup(?)。 ●?WSAENETDOWN:Windows套接口實現(xiàn)檢測到網(wǎng)絡(luò)子系統(tǒng)失效。 ●?WSAEFAULT:namelen參數(shù)不夠大。 ●?WSAEINPROGRESS:一個阻塞的Windows套接口調(diào)用正在運行中。 ●?WSAENOTCONN:套接口未建立連接。 ●?WSAENOTSOCK:描述字不是一個套接口。 4.函數(shù)使用說明
getpeername(?)函數(shù)用于從套接口s中獲取與它綁定的遠程協(xié)議的地址信息,并把它存放在sockaddr類型的name結(jié)構(gòu)中。它只能用于已經(jīng)建立連接的套接口。對于數(shù)據(jù)報類型的套接口來說,它只能返回先前調(diào)用connect(?)函數(shù)時使用的對等端信息,在sendto(?)函數(shù)中使用過的對等端信息不能被返回。 8.3.3獲得套接口本地協(xié)議地址——getsockname(?) 1.函數(shù)格式
getsockname(?)函數(shù)的格式如下:
intgetsockname( SOCKETs, structsockaddrFAR*name, intFAR*namelen ); 2.函數(shù)參數(shù)說明 該函數(shù)的參數(shù)說明如下: ●?s:傳入?yún)?shù),標識一個套接口的描述字。 ●?name:傳出參數(shù),指向返回的本地協(xié)議地址的指針。 ●?namelen:傳出參數(shù),本地協(xié)議地址長度。當函數(shù)調(diào)用完成時,??它可以返回實際的本地地址長度。 3.函數(shù)返回信息 調(diào)用該函數(shù)時若無錯誤發(fā)生,則getsockname(?)函數(shù)返回0。如果調(diào)用失敗,則返回SOCKET_ERROR錯誤信息,應(yīng)用程序可通過WSAGetLastError(?)函數(shù)來獲取如下的錯誤代碼: ●?WSANOTINITIALISED:在使用此API之前應(yīng)成功調(diào)用WSAStartup(?)。 ●?WSAENETDOWN:Windows套接口實現(xiàn)檢測到網(wǎng)絡(luò)子系統(tǒng)失效。 ●?WSAEFAULT:namelen參數(shù)不夠大。 ●?WSAEINPROGRESS:一個阻塞的Windows套接口調(diào)用正在運行中。 ●?WSAENOTSOCK:描述字不是一個套接口。 ●WSAEINVAL:套接口未用bind(?)捆綁。 4.函數(shù)使用說明
getsockname(?)函數(shù)用于獲取一個套接口的協(xié)議地址,它用于一個已綁定或已連接套接口。本調(diào)用特別適用于如下情況:未調(diào)用bind(?)就調(diào)用了connect(?),這時惟有g(shù)etsockname(?)調(diào)用可以獲知系統(tǒng)內(nèi)定的本地地址。在返回時,namelen參數(shù)包含了名字的實際字節(jié)數(shù)。 若一個套接口與INADDR_ANY綁定,即該套接口可以用任意的主機地址,此時除非調(diào)用connect(?)或accept(?)來連接,否則getsockname(?)將不會返回主機IP地址的任何信息。除非套接口被連接,Windows套接口應(yīng)用程序不應(yīng)假設(shè)IP地址會從INADDR_ANY變成其他地址。這是因為對于一個有多個IP地址的主機來說,除非套接口被連接,否則該套接口所用的IP地址是不可知的(即不能被確定是哪一個)。 8.3.4根據(jù)主機名取得主機信息——gethostbyname(?)或WSAAsyncGetHostByName(?) gethostbyname(?)和WSAAsynGetHostByName(?)這兩個WinsockAPI函數(shù)從主機數(shù)據(jù)庫中取回與指定的主機名對應(yīng)的主機信息。這兩個函數(shù)均返回一個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:該字段是正式的主機名。 ●?h_aliases:它是二維字符指針,返回一臺主機的所有別名(即別名列表)。 ●?h_addrtype:表示主機地址類型,如AF_INET表示IPv4地址。 ●?h_length:該字段可以返回主機地址的字節(jié)數(shù)。 ●?h_addr_list:該字段返回一個主機的所有IP地址,因為一臺主機可以分配若干個IP地址(當然這主要是對服務(wù)器而言的)。這個數(shù)組中的每個地址都是按網(wǎng)絡(luò)字節(jié)順序返回的。一般情況下,應(yīng)用程序都采用該數(shù)組中的第一個地址。但是,如果返回的地址不止一個,應(yīng)用程序就會相應(yīng)地選擇一個最恰當?shù)牡刂?,而不是一直都用第一個地址。 ●?h_addr:是為了保持向后兼容而定義的字段,一般很少使用。
1.函數(shù)格式 在Winsock1中提供的gethostbyname(?)函數(shù)的格式是:
structhostentFAR*gethostbyname( constcharFAR*name );
在Winsock1中提供的異步擴WSAAsyncGetHostByName(?)函數(shù)的格式是:
HANDLEWSAAsyncGetHostByName( HWNDhWnd, unsignedintwMsg, constcharFAR*name, charFAR*buf, intbuflen ); 2.函數(shù)參數(shù)說明
gethostbyname(?)函數(shù)中各參數(shù)的說明如下: ●?name:傳入?yún)?shù),是一個指向主機名的指針。
WSAAsyncGetHostByName(?)函數(shù)是一個Windows異步擴展函數(shù),它在函數(shù)結(jié)束時,利用Windows消息向應(yīng)用程序發(fā)出通知,其各參數(shù)的含義是: ●?hWnd:傳入?yún)?shù),??是一個窗口句柄,??表示當異步請求完成時,該窗口句柄應(yīng)該收到一條消息。 ●?wMsg:傳入?yún)?shù),當異步請求完成時,將要接收的消息。 ●?name:傳入?yún)?shù),指向主機名的指針。 ●?buf:傳出參數(shù),??接收hostent數(shù)據(jù)的數(shù)據(jù)區(qū)指針。注意該數(shù)據(jù)區(qū)必須大于hostent結(jié)構(gòu)的大小,這是因為WindowsSockets實現(xiàn)不僅要用該數(shù)據(jù)區(qū)容納hostent結(jié)構(gòu),而且hostent結(jié)構(gòu)的成員引用的所有數(shù)據(jù)也要在該區(qū)域內(nèi)。建議用戶提供一個MAXGETHOSTSTRUCT字節(jié)大小的緩沖區(qū)。 ●?buflen:傳入?yún)?shù),上述數(shù)據(jù)區(qū)的大小。 3.函數(shù)返回信息 調(diào)用該函數(shù)時如果沒有錯誤發(fā)生,gethostbyname(?)函數(shù)返回如上所述的一個指向hostent結(jié)構(gòu)的指針。如果調(diào)用失敗則返回一個空指針,應(yīng)用程序可以通過WSAGetLastError(?)來得到一個特定的錯誤代碼,錯誤代碼說明如下: ●?WSANOTINTIALISED:在應(yīng)用這個API前,必須成功調(diào)用WSAStartup(?)。 ●?WSAENETDOWN:WindowsSockets實現(xiàn)檢測到了網(wǎng)絡(luò)子系統(tǒng)的錯誤。 ●?WSAHOST_NOT_FOUND:沒有找到授權(quán)應(yīng)答主機。 ●?WSATRY_AGAIN:沒有找到非授權(quán)主機,或者服務(wù)器故障(SERVERFAIL)。 ●?WSANO_RECOVERY:無法恢復的錯誤,如查詢有格式錯誤(FORMERR)、拒絕服務(wù)(REFUSED)沒有通信處理機、(NOTIMP)。 ●?WSANO_DATA:有效的名字,但沒有關(guān)于請求類型的數(shù)據(jù)記錄。 ●?WSAEINPROGRESS:一個阻塞的WindowsSockets操作正在進行。 ●?WSAEINTR:阻塞調(diào)用被WSACancelBlockingCall(?)取消了。
4.異步擴展函數(shù)返回信息
WSAAsyncGetHostByName(?)函數(shù)是gethostbyname(?)函數(shù)的Windows異步擴展函數(shù)。所謂“異步”,指的是WindowsSockets的實現(xiàn)啟動該操作后立刻回到調(diào)用方,并傳回一個異步任務(wù)句柄,應(yīng)用程序可以用它來標識該操作。 當異步操作完成時,如果成功則將主機名和地址信息拷貝到buf緩沖區(qū)中,同時向句柄為hWnd的應(yīng)用程序窗口發(fā)送一條消息(wMsg)。wParam參數(shù)包含了初次函數(shù)調(diào)用時返回的異步任務(wù)句柄,lParam的高16位包含著錯誤代碼,該代碼可以是Winsock2.h中定義的任何錯誤。錯誤代碼為0說明異步操作成功,在成功完成的情況下,提供給初始函數(shù)調(diào)用的緩沖區(qū)中包含了一個hostent結(jié)構(gòu)。為存取該結(jié)構(gòu)中的元素,初始的緩沖區(qū)指針應(yīng)置為hostent結(jié)構(gòu)的指針。
若錯誤代碼為WSAENOBUFS,則說明在初始調(diào)用時由buflen指出的緩沖區(qū)大小對于容納所有的結(jié)果信息來說太小了。在這種情況下,lParam的低16位提供所有信息所需的緩沖區(qū)大小。如果應(yīng)用程序認為獲取的數(shù)據(jù)不夠,它就可以在設(shè)置了足夠容納所需信息的緩沖區(qū)(也就是大于lParam低16位提供的數(shù)值)后,重新調(diào)用WSAAsyncGetHostByName(?)函數(shù)。 錯誤代碼和緩沖區(qū)大小應(yīng)使用WSAGETASYNCERROR和WSAGETASYNCBUFLEN宏從lParam中取出。這兩個宏的定義如下:
#defineWSAGETASYNCERROR(lParam) HIWORD(lParam) #defineWSAGETASYNCBUFLEN(lParam) LOWORD(lParam)
使用這些宏可以最大限度地提高應(yīng)用程序源代碼的可移植性。 函數(shù)的返回值指出異步操作是否成功啟動,注意它并不隱含操作本身的成功或失敗(后面要介紹的其他異步函數(shù)的返回值也與它類似)。
若操作成功啟動,則WSAAsyncGet-HostByName(?)返回一個HANDLE類型的非0值,它用來標識該異步請求任務(wù)的句柄。通過該句柄使用WSACancelAsyncRequest(?)函數(shù)可取消該操作,也可通過檢查wParam消息參數(shù),以匹配異步操作和完成消息。如果異步操作不能啟動,WSAAsyncGetHostByName(?)返回一個0值,并且可使用WSAGetLastError(?)函數(shù)來獲取如下的錯誤代碼: ●WSANOTINITIALISED:在使用本API前必須進行一次成功的WSAStartup(?)調(diào)用。 ●?WSAENETDOWN:WindowsSockets實現(xiàn)已檢測到網(wǎng)絡(luò)子系統(tǒng)故障。 ●?WSAEINPROGRESS:一個阻塞的WindowsSockets操作正在進行。 ●?WSAEWOULDBLOCK:本異步操作此時由于WindowsSockets實現(xiàn)的資源或其他限制的制約而無法調(diào)度。在應(yīng)用程序的窗口收到消息時可能會設(shè)置下列錯誤代碼,它們可以通過WSAGETA-SYNCERROR宏從應(yīng)答的消息lParam中取出: ●?WSAENETDOWN:WindowsSockets實現(xiàn)已檢測到網(wǎng)絡(luò)子系統(tǒng)故障。 ●?WSAENOBUFS:可用的緩沖區(qū)空間不足或沒有。 ●?WSAHOST_NOT_FOUND:未找到授權(quán)應(yīng)答主機。 ●?WSATRY_AGAIN:未找到非授權(quán)應(yīng)答主機,或SERVERFAIL。 ●?WSANO_RECOVERY:不可恢復性錯誤。 ●?WSANO_DATA:無請求類型的數(shù)據(jù)記錄。 8.3.5根據(jù)主機地址取得主機信息——gethostbyaddr(?)或WSAAsyncGetHostByAddr(?)
這兩個函數(shù)可以根據(jù)主機的IP地址取得主機名和主機地址等信息。
1.函數(shù)格式 在Winsock1中提供的gethostbyaddr(?)函數(shù)的格式是:
structhostentFAR*gethostbyaddr( constcharFAR*addr, intlen, inttype );
在Winsock1中提供的異步擴展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ù)返回信息 這兩個函數(shù)返回的信息與通過名稱獲取主機信息的gethostbyname(?)函數(shù)相同。
8.3.6根據(jù)協(xié)議名取得主機協(xié)議信息——getprotobyname(?)或WSAAsync-GetProtoByName(?)
函數(shù)getprotobyname()WSAAsyncGetProtoByName()可以根據(jù)協(xié)議名稱返回對應(yīng)的相關(guān)協(xié)議信息。它們都要使用到一個與協(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:它是二維字符指針,返回一個協(xié)議的所有別名。 ●?p_proto:以主機字節(jié)順序排列的協(xié)議號。 1.函數(shù)格式 在Winsock1中提供的getprotobyname(?)函數(shù)的格式是:
structprotoentFAR*getprotobyname( constcharFAR*name );
在Winsock1中提供的異步擴展WSAAsyncGetProtoByName(?)函數(shù)的格式是:
HANDLEWSAAsyncGetProtoByName( HWNDhWnd, unsignedintwMsg, constcharFAR*name, charFAR*buf, intbuflen ); 2.函數(shù)參數(shù)說明
getprotobyname(?)函數(shù)中的參數(shù)name為傳入?yún)?shù),指向協(xié)議名的指針。 異步擴展格式中的buf是接收protoent數(shù)據(jù)的緩沖區(qū)指針,buflen為該緩沖區(qū)的大小。其他參數(shù)與WSAAsyncGetHostByName(?)函數(shù)中的參數(shù)相同,返回信息的含義也一樣。
3.函數(shù)返回信息 如果沒有錯誤發(fā)生,getprotobyname(?)返回如上所述的一個指向protoent結(jié)構(gòu)的指針,如果調(diào)用失敗,則返回一個空指針。應(yīng)用程序可以通過WSAGetLastError(?)來得到一個如下所示的特定錯誤代碼: ●?WSANOTINTIALISED:在應(yīng)用這個API前,必須成功調(diào)用WSAStartup(?)。 ●?WSAENETDOWN:WindowsSockets實現(xiàn)檢測到了網(wǎng)絡(luò)子系統(tǒng)的錯誤。 ●?WSANO_RECOVERY:無法恢復的錯誤,如FORMERR、REFUSED、NOTIMP等。 ●?WSANO_DATA:有效的名字,但沒有關(guān)于請求類型的數(shù)據(jù)記錄。
●?WSAEINPROGRESS:一個阻塞的WindowsSockets操作正在進行。 ●?WSAEINTR:阻塞調(diào)用被WSACancelBlockingCall(?)取消了。 ●?WSAHOST_NOT_FOUND:沒有找到協(xié)議。 ●?WSATRY_AGAIN:非正式的協(xié)議沒有找到或服務(wù)器失敗。 ●?WSAEFAULT:name參數(shù)不在有效的用戶地址空間。 8.3.7根據(jù)協(xié)議號取得主機協(xié)議信息——getprotobynumber(?)或WSAAsyncGetProtoByNumber(?) getprotobynumber(?)和WSAAsyncGetProtoByNumber返回對應(yīng)于給定協(xié)議號的相關(guān)協(xié)議信息。
1.函數(shù)格式 在Winsock1中提供的getprotobynumber(?)函數(shù)的格式是:
structprotoentFAR*getprotobynumber( intnumber );
在Winsock1中提供的異步擴展WSAAsyncGetProtoByNumber(?)函數(shù)的格式是:
HANDLEWSAAsyncGetProtoByNumber( HWNDhWnd, unsignedintwMsg, intnumber, charFAR*buf, intbuflen ); 2.函數(shù)參數(shù)說明 參數(shù)number表示傳入?yún)?shù),是一個以主機字節(jié)順序排列的協(xié)議號。異步擴展格式中的其他參數(shù)與WSAAsyncGetHostByName(?)函數(shù)中的參數(shù)含義相同。
3.函數(shù)返回信息 函數(shù)的返回信息與通過協(xié)議名獲取主機協(xié)議信息時的情況相同。 8.3.8根據(jù)服務(wù)名取得相關(guān)服務(wù)信息——?getservbyname(?)或WSAAsync-GetServByName(?) getservbyrvame(?)和WSAAsyncGetServByName(?)函數(shù)用于返回對應(yīng)于給定服務(wù)名和協(xié)議名的相關(guān)服務(wù)信息。這兩個函數(shù)都要用到一個如下所示的結(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ù)時需要用到的端口號,返回的端口號是以網(wǎng)絡(luò)字節(jié)順序排列的。 ●?s_proto:連接該服務(wù)時用到的協(xié)議名。 1.函數(shù)格式 在Winsock1中提供的getservbyname(?)函數(shù)的格式是:
structserventFAR*getservbyname( constcharFAR*name, constcharFAR*proto );
在Winsock1中提供的異步擴展WSAAsyncGetServByName(?)函數(shù)的格式是: HANDLEWSAAsyncGetServByName( HWNDhWnd, unsignedintwMsg, constcharFAR*name, constcharFAR*proto, charFAR*buf, intbuflen ); 2.函數(shù)參數(shù)說明 這兩個函數(shù)中各參數(shù)的說明如下: ●?name:傳入?yún)?shù),一個指向服務(wù)名的指針。 ●proto:傳入?yún)?shù),指向協(xié)議名的指針(可選)。如果這個指針為空,getservbyname(?)返回第一個name與s_name或者某一個s_aliases匹配的服務(wù)條目。否則,getservbyname(?)對name和proto都進行匹配。 其他參數(shù)與WSAAsyncGetHostByName(?)函數(shù)中的參數(shù)含義相同。 8.3.9根據(jù)端口號取得相關(guān)服務(wù)信息——getservbyport(?)或WSAAsync-GetServByPort(?) getservbyport(?)和WSAAsyncGetServByPort(?)函數(shù)用于返回對應(yīng)于給定端口號和協(xié)議名的相關(guān)服務(wù)信息。
1.函數(shù)格式 在Winsock1中提供的getservbyport(?)函數(shù)的格式是:
structserventFAR*getservbyport( intport, constcharFAR*proto );
在Winsock1中提供的異步擴展WSAAsyncGetServByPort(?)函數(shù)的格式是:
HANDLEWSAAsyncGetServByPort( HWNDhWnd, unsignedintwMsg, intport, constcharFAR*proto, charFAR*buf, intbuflen ); 2.函數(shù)參數(shù)說明 這兩個函數(shù)中需要說明的參數(shù)如下: ●?port:傳入?yún)?shù),給定的端口號,以網(wǎng)絡(luò)字節(jié)順序排列。 ●proto:傳入?yún)?shù),指向協(xié)議名的指針(可選)。如果這個指針為空,getservbyport(?)返回第一個port與s_port匹配的服務(wù)條目。否則,getservbyport(?)對port和proto都進行匹配。 其他參數(shù)與WSAAsyncGetHostByName(?)函數(shù)中的參數(shù)含義相同。 8.3.10網(wǎng)絡(luò)信息獲取函數(shù)應(yīng)用實例 本小節(jié)舉一個實例來說明以上介紹的網(wǎng)絡(luò)信息獲取函數(shù)的用法。本實例只使用了三個比較典型的函數(shù),其他函數(shù)的用法與此類似。要說明的是,雖然這只是一個關(guān)于網(wǎng)絡(luò)信息獲取函數(shù)用法的實例,但該程序也是一個非常有用的實用程序,它可以獲得一臺主機的主機名、主機別名(如果有的話)、主機IP地址列表等信息。
/*************************************************************************
調(diào)試環(huán)境:VC++6.0
程序名稱:host.cpp
程序功能:該程序使用網(wǎng)絡(luò)信息獲取函數(shù)取得主機的有關(guān)信息,在程序中使用了以下三個函數(shù): gethostname(?) gethostbyname(?) getprotobyname(?)
命令格式:host**************************************************************************/ #include<winsock2.h> #include<stdio.h> #include<stdlib.h> voidmain(?) { WSADATA wsaData; int n; //存放主機名稱
char hostname[256]; //主機信息指針
hostent *pHostent; //主機協(xié)議信息指針
protoent *pProtoent; structsockaddr_in sa; if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0) { printf("FailedtoloadWinsock.\n"); return; } printf("---------------------------------------------\n");//獲得主機名
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ù)主機名獲取主機信息
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)中的主機地址
for(n=0;pHostent->h_addr_list[n];n++){memcpy(&sa.sin_addr.s_addr,pHostent->h_addr_list[n],pHostent->h_length);//輸出主機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(?); }
程序的運行結(jié)果如圖8-1所示。圖8-1網(wǎng)絡(luò)信息獲取函數(shù)使用實例程序的運行結(jié)果8.4套接口選項函數(shù) 8.4.1套接口選項函數(shù)說明
1.函數(shù)格式 套接口選項獲取函數(shù)getsockopt(?)的格式如下:
intsetsockopt( SOCKETs, intlevel, intoptname, constcharFAR*optval, intoptlen );
套接口選項設(shè)置函數(shù)setsockopt(?)的格式如下:
intgetsockopt( SOCKETs, intlevel, intoptname, charFAR*optval, intFAR*optlen ); 2.函數(shù)參數(shù)說明
setsockopt(?)函數(shù)和getsockopt(?)函數(shù)的參數(shù)是一樣的,但 setsockopt(?)函數(shù)的optval和optlen選項應(yīng)該由應(yīng)用程序填寫,而getsockopt(?)函數(shù)的這兩個選項是返回值,由系統(tǒng)來填寫。 函數(shù)中各參數(shù)的含義如下: ●s:傳入?yún)?shù),參數(shù)s指定一個有效的套接口,我們要對這個套接口的選項進行操作。 ●?level:傳入?yún)?shù),套接口選項定義的級別(層次)。常用的級別有SOL_SOCKET、IPPROTO_IP和IPPROTO_TCP,在8.4.2~8.4.4節(jié)將對這些級別對應(yīng)的選項進行專門介紹。 ●?optname:傳入?yún)?shù),需設(shè)置或獲取的套接口選項,這些選項的名稱均是在Winsock頭文件內(nèi)定義的常數(shù)值。 ●?optval:對于setsockopt(?)函數(shù)來說,?它是傳入?yún)?shù);對于getsockopt(?)函數(shù)來說,它是傳出參數(shù)。該參數(shù)是指向存放選項值緩沖區(qū)的指針。 ●?optlen:對于setsockopt(?)函數(shù)來說,?它是傳入?yún)?shù);對于getsockopt(?)函數(shù)來說,它既是傳出參數(shù)也是傳入?yún)?shù)。該參數(shù)是指向optval緩沖區(qū)長度(或套接口選項變量的長度)的指針。 3.函數(shù)返回信息 若函數(shù)調(diào)用時無錯誤發(fā)生,則setsockopt(?)函數(shù)和getsockopt(?)函數(shù)都返回0。如果調(diào)用發(fā)生錯誤,則返回SOCKET_ERROR錯誤信息,應(yīng)用程序可通過WSAGetLastError(?)函數(shù)獲取對錯誤信息的進一步說明。以下是錯誤代碼的含義說明: ●?WSANOTINITIALISED:在使用此API之前應(yīng)成功調(diào)用WSAStartup(?)。 ●?WSAENETDOWN:Windows套接口實現(xiàn)已檢測到網(wǎng)絡(luò)子系統(tǒng)失效。 ●?WSAEFAULT:setsockopt(?)函數(shù)返回時,表示optval不是進程地址空間中的一個有效部分;getsockopt(?)函數(shù)返回時,表示optlen參數(shù)非法。 ●?WSAEINPROGRESS:一個阻塞的Windows套接口調(diào)用正在運行中。 ●?WSAEINVAL:level值非法,或optval中的信息非法。 ●?WSAENETRESET:當SO_KEEPALIVE設(shè)置后連接超時。 ●?WSAENOPROTOOPT:未知或不支持選項。其中,SOCK_STREAM類型的套接口不支持SO_BROADCAST選項,SOCK_DGRAM類型的套接口不支持SO_DONTLINGER、SO_KEEPALIVE、SO_LINGER和SO_OOBINLINE選項。 ●?WSAENOTCONN:當設(shè)置SO_KEEPALIVE后連接被復位。 ●?WSAENOTSOCK:描述字不是一個套接口。 8.4.2SOL_SOCKET選項級別
SOL_SOCKET選項級別主要針對傳輸層協(xié)議(TCP或UDP)。在SOL_SOCKET選項級別下,套接口的選項有兩種類型:一種是值為布爾型(BOOL)的選項,這種選項可以允許或禁止一種特性;另一種是值為整型(int)或結(jié)構(gòu)型(StructLinger)的選項,這種選項可以用來設(shè)置系統(tǒng)工作時的某些參數(shù)。
允許一個布爾型選項,則將optval指向一個非零的整型數(shù);禁止一個布爾型選項,則可以將optval指向一個等于零的整型數(shù)。對于布爾型選項,optlen應(yīng)等于sizeof(int)。對于非布爾型的其他選項,optval應(yīng)該指向包含所需選項的整型量或結(jié)構(gòu)量,而optlen則為整形量或結(jié)構(gòu)量的長度。 還要注意一個問題,套接口的有些屬性值既可以設(shè)置(即可以使用setsockopt(?)函數(shù)),也可以獲取(即使用getsockopt(?)函數(shù)),但有些套接口屬性只能獲取或只能設(shè)置。 后面要介紹的其他兩種選項級別(IPPROTO_IP和IPPROTO_TCP)與SOL_SOCKET選項級別的情況類似。 表8-1所示為在SOL_SOCKET選項級別下的各種選項。表8-1SOL_SOCKET選項級別下的各選項 (1)?SO_ACCEPTCONN:該選項只能獲取。如果已通過listen(?)函數(shù)調(diào)用,??套接口將進入監(jiān)聽模式,這時獲取這個選項時就會返回TRUE。數(shù)據(jù)報類型的套接口(SOCK_DGRAM)不支持這一選項。
(2)?SO_BROADCAST:??該選項可以獲取也可以設(shè)置。如果指定的套接口該選項已經(jīng)設(shè)置為TRUE,則允許套接口廣播收發(fā)信息。該選項只有對非SOCK_STREAM類型的所有套接口才是有效的。
廣播是一種特殊的數(shù)據(jù)發(fā)送方法,使本地子網(wǎng)上的所有機器都能收到相同的數(shù)據(jù)。廣播通信的缺點在于假如同時有許多進程發(fā)送廣播數(shù)據(jù),網(wǎng)絡(luò)立刻就會擁擠不堪,造成網(wǎng)絡(luò)性能大大降低,甚至有可能陷入癱瘓。要想接收一條廣播消息,首先必須啟用廣播選項,然后使用某個數(shù)據(jù)報接收函數(shù),比如recvfrom(?)或WSARecvFrom(?)。該選項的設(shè)置方法如下: …… BOOLbBroadcast=TRUE; //創(chuàng)建一個數(shù)據(jù)報套接口
s=socket(AF_INET,SOCK_DGRAM,0); …… //設(shè)置廣播選項
if(setsocketopt(s,SOL_SOCKET,SO_BROADCAST,(char*)&bBroadcast,sizeof(BOOL))==SOCKET_ERROR) { printf(''setsocketopt(?)Error:u%\n'',WSAGetLastError(?)); return; } …… (3)?SO_CONNECT_TIME:該選項只能獲取。它是一個微軟Windows操作系統(tǒng)專用選項,用于返回連接建立的時間,以秒為單位。該選項可以在客戶端的SOCKET句柄上調(diào)用,以判斷連接是否已經(jīng)建立,以及建立了多長時間。若套接口當前尚未建立連接,返回值便是0xFFFFFFFF。
(4)?SO_DEBUG:該選項值可以獲取,也可以設(shè)置。在應(yīng)用程序設(shè)置了SO_DEBUG選項的情況下,系統(tǒng)將記錄調(diào)試信息。至于調(diào)試信息如何展示,要取決于服務(wù)提供者的基層實施方式。要想打開調(diào)試信息,可調(diào)用setsockopt(?)函數(shù)設(shè)置SO_DEBUG為TRUE。若用SO_DEBUG選項調(diào)用getsockopt(?)函數(shù),會返回TRUE或FALSE,分別代表允許和禁止記錄調(diào)試信息。但目前尚無任何一種Win32平臺支持的SO_DEBUG選項。 (5)?SO_LINGER:該選項值可以獲取,也可以設(shè)置。該選項不能使用在SOCK_DGRAM類型的套接口上。它用于控制在closesocket(?)函數(shù)已執(zhí)行的情況下,如何處理套接口數(shù)據(jù)排列上未發(fā)送完畢的數(shù)據(jù)。該選項要通過linger結(jié)構(gòu)來設(shè)置,該結(jié)構(gòu)的定義如下:
structlinger{ intl_onoff; intl_linger; };
l_onoff字段用來控制SO_LINGER選項的打開或關(guān)閉,為了使該選項起作用,該字段應(yīng)該設(shè)置為一個非0的值。l_linger字段表示延遲時間,以秒為單位。 當l_onoff和l_linger字段取不同的值時,系統(tǒng)的操作方式也不同,它們的取值情況如表8-2所示。表8-2SO_LINGER選項取值情況說明 (6)?SO_DONTLINGER:該選項值可以獲取,也可以設(shè)置。若在一個流類套接口上設(shè)置了SO_DONTLINGER選項,也就是說將linger結(jié)構(gòu)的l_onoff域設(shè)為0,則closesocket(?)調(diào)用立即返回,但是,如果可能,排隊的數(shù)據(jù)將在套接口關(guān)閉之前被發(fā)送。SO_DONTLINGER和SO_LINGER選項將直接影響使用closesocket(?)函數(shù)關(guān)閉一個套接口時系統(tǒng)對套接口的操作行為。表8-3總結(jié)了這兩個選項對套接口關(guān)閉方式的影響。表8-3SO_DONTLINGER和SO_LINGER選項對套接口關(guān)閉方式的影響 (7)?SO_DONTROUTE:該選項可以獲取,也可以設(shè)置。
(8)?SO_ERROR:該選項只能獲取,用于返回以具體套接口為基礎(chǔ)的錯誤代碼,在返回后系統(tǒng)一般將該選項設(shè)置為0。
(9)?SO_KEEPALIVE:該選項可以獲取,也可以設(shè)置,它只適用于以TCP為基礎(chǔ)的套接口。在Windows95及Windows98操作系統(tǒng)中,這兩個鍵都位于下述注冊表路徑中:\HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\VxD\MSTCP
而在WindowsNT和Windows2000中,這兩個鍵位于下述位置:
\HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\TCPIP\Parameters服務(wù)器(例如FTP服務(wù)器)一般要設(shè)置該選項,這樣當客戶在非正常終止連接的情況下,經(jīng)過一段時間后,服務(wù)器也能終止該連接。
(10)?SO_MAX_MSG_SIZE:該選項只能獲取。
(11)?SO_OOBINLINE:該選項可以獲取,也可以設(shè)置。 (12)?SO_PROTOCOL_INFO:該選項只能獲取,獲取WSAPROTCOL_INFO結(jié)構(gòu)中與套接口關(guān)聯(lián)在一起的協(xié)議特征信息。該選項由Winsock2支持。
(13)?SO_RCVBUF:該選項可以獲取,也可以設(shè)置。
(14)?SO_SNDBUF:該選項可以獲取,也可以設(shè)置。與SO_RCVBUF選項相對應(yīng),該選項用于確定發(fā)送緩沖區(qū)的大小。
(15)?SO_TYPE:該選項只能獲取,??用于返回指定套接口的類型??赡艿奶捉涌陬愋桶⊿OCK_DGRAM、SOCK_STREAM和SOCK_RAW。
(16)?SO_SNDTIMEO:該選項可以獲取,也可以設(shè)置。 (17)?SO_RCVTIMEO:該選項可以獲取,也可以設(shè)置。
(18)?SO_REUSEADDR:該選項可以獲取,也可以設(shè)置,表示該套接口能和一個已在使用中的地址捆綁。
(19)?SO_EXCLUSIVEADDRUSE:該選項可以獲取,也可以設(shè)置。該選項的作用是禁止其他進程在一個本地地址上使用SO_REUSEADDR(重復使用地址)。 8.4.3IPPROTO_IP選項級別 該選項級別包括的主要選項如表8-4所示。表8-4IPPROTO_IP級別套接口選項 (1)?IP_OPTIONS:該選項可以獲取,也可以設(shè)置。它是專門針對IP數(shù)據(jù)報選項字段的,通過該選項字段,用戶可以獲取IP數(shù)據(jù)報頭選項字的設(shè)置情況,也可以對IP選項字段進行設(shè)置。IP數(shù)據(jù)報選項的格式如圖2-12所示。 ●記錄路由:IP數(shù)據(jù)報在傳輸過程中,每經(jīng)過一個路由器,路由器就將自己的IP地址添加到IP數(shù)據(jù)報頭內(nèi)的選項字段位置。 ●記錄時間戳:IP數(shù)據(jù)報在傳輸過程中,每經(jīng)過一個路由器,路由器就將自己的IP地址及時間添加到IP數(shù)據(jù)報頭內(nèi)的選項字段位置。 ●寬松源路由選擇:IP數(shù)據(jù)報在傳輸過程中,要經(jīng)過IP數(shù)據(jù)報選項內(nèi)列出的每個IP地址,但也可以經(jīng)過其他的IP地址。 ●嚴格源路由選擇:IP數(shù)據(jù)報在傳輸過程中,只能經(jīng)過IP數(shù)據(jù)報選項內(nèi)列出的每個IP地址。 下面我們以記錄路由為例說明如何進行IP_OPTIONS選項的設(shè)置。 第一步:先聲明一個數(shù)據(jù)結(jié)構(gòu),它包括選項碼、選項長度、偏移量與選項數(shù)據(jù)4個字段。要注意的是,由于IP選項最長為40字節(jié),所以所定義的結(jié)構(gòu)長度不能超過這個數(shù)值。
第二步:根據(jù)要設(shè)置的選項,對說明的選項數(shù)據(jù)結(jié)構(gòu)各字段進行初始化。選項碼字段的值見2.3.3小節(jié)。 第三步:使用setsockopt(?)函數(shù)對IP_OPTIONS選項進行設(shè)置。 以上三步對應(yīng)的代碼如下:
//定義一個數(shù)據(jù)結(jié)構(gòu)
structip_oprion_hdr { unsignedchar code; unsignedchar length; unsignedchar offset; unsignedlong addrs[9]; }opthdr; …… //對定義的結(jié)構(gòu)進行初始化
byzero((char*)&opthdr,sizeof(opthdr)); //記錄路由選項碼
opthdr.code=0x87; //總的選項長度
opthdr.length=39; //選項數(shù)據(jù)的初始位置
opthdr.offset=4; //設(shè)置記錄路由選項
ret=setsockopt(s,IPPROTO_IP,IP_OPTIONS,(char*)&opthdr,sizeof(opthdr)); …… (2)?IP_HDRINCL:該選項可以獲取,也可以設(shè)置。
(3)?IP_TOS:該選項可以獲取,也可以設(shè)置。
(4)?IP_TTL:該選項可以獲取,也可以設(shè)置。
(5)?IP_MULTICAST_TTL:該選項可以獲取,也可以設(shè)置。
(6)?IP_MULTICAST_IF:該選項可以獲取,也可以設(shè)置,用于為IP多播設(shè)置一個本地接口,本地機器以后發(fā)出的任何多播數(shù)據(jù)都會經(jīng)由該接口傳送出去。 (7)?IP_MULTICAST_LOOP:該選項可以獲取,也可以設(shè)置。該選項用于控制發(fā)送的多播數(shù)據(jù)是否進入本地套接口的輸入數(shù)據(jù)隊列中。
(8)?IP_ADD_MEMBERSHIP:該選項只能設(shè)置。該選項實際是由Winsock1提供的一個方法,可將一個套接口加入一個指定的IP多播組,此時需要用socket函數(shù)來創(chuàng)建地址族為AF_INET的一個套接口,同時將套接口的類型設(shè)為SOCK_DGRAM。要想將套接口加入一個多播組,要使用如下結(jié)構(gòu):
srtuctip_mreq{ structin_addr imr_multiaddr; structin_addr imr_interface; }; 在ip_mreq結(jié)構(gòu)中,imr_multiaddr對應(yīng)于套接口將要加入的那個多播組的二進制格式地址;而imr_interface對應(yīng)于將要用來收發(fā)多播數(shù)據(jù)的一個本地接口。 (9)IP_DROP_MEMBERSHIP:該選項只能設(shè)置,用于將套接口從指定的IP組內(nèi)刪去,即撤銷其成員資格。該選項正好與IP_ADD_MEMBERSHIP相反。使用ip_mreq結(jié)構(gòu)調(diào)用該選項,并在該結(jié)構(gòu)中放入與當初加入指定多播組時相同的值,套接口便會從那個組內(nèi)刪去,脫離成員關(guān)系。
(10)?IP_DONTFRAGMENT:該選項可以獲取,也可以設(shè)置,用來控制是否對IP數(shù)據(jù)報進行分段。如果設(shè)置為TRUE,IP數(shù)據(jù)報在傳輸過程中就不需要對IP數(shù)據(jù)報進行分段處理,當然這樣就存在一個問題,當一個IP數(shù)據(jù)報的大小已經(jīng)超過了最大數(shù)據(jù)傳輸單元(MTU)的值時,這個數(shù)據(jù)報就會被丟棄,同時向發(fā)送者返回一條ICMP錯誤消息,提示用戶數(shù)據(jù)需要分段,但未設(shè)置分段標志位。 8.4.4IPPROTO_TCP選項級別 該選項是針對TCP協(xié)議的。在Winsock中僅有一個IPPROTO_TCP級別的選項,即TCP_NODELAY選項,該選項用來打開或關(guān)閉Nagle算法。如果該選項的值為TRUE,則在對應(yīng)的套接口上禁止使用Nagle算法。在系統(tǒng)默認情況下,Nagle算法是打開的,該選項只適用于流式套接口(SOCK_STREAM),其地址族為AF_INET。這個選項可用在所有Winsock版本上,并得到了所有Win32平臺的支持。
Nagle算法將未確認的數(shù)據(jù)存入緩沖區(qū),直到蓄足一個包后一起發(fā)送,這樣做的好處是可以減少主機發(fā)送的零碎小數(shù)據(jù)包的數(shù)目,以減少網(wǎng)絡(luò)通信的開銷,提高系統(tǒng)的吞吐量。但對于某些應(yīng)用來說,這種算法將降低系統(tǒng)性能,例如交互性較強的Telnet應(yīng)用程序,用戶可通過它登錄至一臺遠程機器,然后向其傳送命令。通常,用戶每秒只會進行少量的鍵擊,若使用Nagle算法,便會造成響應(yīng)的遲鈍,甚至造成對方主機不予應(yīng)答的錯覺。此時,使用TCP_NODELAY選項可將此算法關(guān)閉,以適應(yīng)一些交互性較強的應(yīng)用程序。應(yīng)用程序編寫者只有在確切了解它的效果并在確實需要的情況下,才可設(shè)置TCP_NODELAY選項,因為在一般的應(yīng)用中如果設(shè)置該選項,則對網(wǎng)絡(luò)性能有明顯的負面影響。 8.4.5套接口屬性設(shè)置和獲取實例 在本實例程序中,使用getsockopt(?)函數(shù)來獲取套接口的類型、接收緩沖和發(fā)送緩沖的大小,然后使用setsockopt(?)函數(shù)對套接口接收緩沖進行重新設(shè)置,并用getsockopt(?)函數(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; //存放選項值
intoptname; //選項的長度
intoptlen;if(WSAStartup(MA
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 中藥香囊文化體驗館行業(yè)跨境出海戰(zhàn)略研究報告
- 保險福利申請協(xié)議
- 2025至2030年中國小型集裝箱拖車數(shù)據(jù)監(jiān)測研究報告
- 新工程合同范本
- 電梯維護保養(yǎng)流程優(yōu)化與實踐
- 房子店面轉(zhuǎn)租合同范本
- 門窗加工改造合同范本
- 項目收購合同范本
- 2025年中國血管造影劑自動注射裝置市場調(diào)查研究報告
- 體育生訓練協(xié)議書范本
- 施工圖設(shè)計技術(shù)交底文檔
- 重慶高校創(chuàng)新團隊建設(shè)計劃結(jié)題驗收報告
- GB/T 8269-2006檸檬酸
- GB/T 28610-2012甲基乙烯基硅橡膠
- GA/T 1780-2021多道心理測試實驗室建設(shè)規(guī)范
- PPT模板第二講運動選材概述運動選材學
- 《龍須溝》賞析課件
- SiN薄膜特性課件
- 加油站班組活動記錄
- 工程倫理第二講工程中的風險、安全與責任課件
- 教育心理學陳琦課件
評論
0/150
提交評論