![網(wǎng)絡編程實用教程_第3章_第1頁](http://file3.renrendoc.com/fileroot_temp3/2022-1/14/fb5b1b68-0075-4549-9da0-ad91176633a7/fb5b1b68-0075-4549-9da0-ad91176633a71.gif)
![網(wǎng)絡編程實用教程_第3章_第2頁](http://file3.renrendoc.com/fileroot_temp3/2022-1/14/fb5b1b68-0075-4549-9da0-ad91176633a7/fb5b1b68-0075-4549-9da0-ad91176633a72.gif)
![網(wǎng)絡編程實用教程_第3章_第3頁](http://file3.renrendoc.com/fileroot_temp3/2022-1/14/fb5b1b68-0075-4549-9da0-ad91176633a7/fb5b1b68-0075-4549-9da0-ad91176633a73.gif)
![網(wǎng)絡編程實用教程_第3章_第4頁](http://file3.renrendoc.com/fileroot_temp3/2022-1/14/fb5b1b68-0075-4549-9da0-ad91176633a7/fb5b1b68-0075-4549-9da0-ad91176633a74.gif)
![網(wǎng)絡編程實用教程_第3章_第5頁](http://file3.renrendoc.com/fileroot_temp3/2022-1/14/fb5b1b68-0075-4549-9da0-ad91176633a7/fb5b1b68-0075-4549-9da0-ad91176633a75.gif)
版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
1、第第3章章 Windows環(huán)境的網(wǎng)絡編程環(huán)境的網(wǎng)絡編程介紹了介紹了Windows Sockets 規(guī)范規(guī)范, 說明了說明了WinSock 規(guī)范與規(guī)范與Berkeley套接口的區(qū)別套接口的區(qū)別, 說明了說明了Winsock 1.1 的庫函數(shù)。的庫函數(shù)。3.1 Windows Sockets規(guī)范規(guī)范3.1.1 概述概述 Microsoft公司以公司以Berkeley Sockets規(guī)范為范例,規(guī)范為范例,定義了定義了Windows Socktes規(guī)范,簡稱規(guī)范,簡稱Winsock規(guī)規(guī)范。這是范。這是Windows操作系統(tǒng)環(huán)境下的套接字網(wǎng)絡應操作系統(tǒng)環(huán)境下的套接字網(wǎng)絡應用程序編程接口(用程序編程接口
2、(API)。)。 圖3.1 網(wǎng)絡應用進程利用Windock進行通信 3.1.2 Windows Sockets規(guī)范規(guī)范 Windows Sockets 規(guī)范是一套開放的、支持多種協(xié)議的Windows下的網(wǎng)絡編程接口。從1991年到1995年,從1.0版發(fā)展到2.0.8版,已成為Windows網(wǎng)絡編程的事實上的標準。1Windows Sockets 1.1版本版本 在Winsock.h包含文件中,定義了所有WinSock 1.1版本庫函數(shù)的語法、相關的符號常量和數(shù)據(jù)結構。庫函數(shù)的實現(xiàn)在WINSOCK.DLL動態(tài)鏈接庫文件中。 (1)WinSock 1.1 全面繼承了全面繼承了Berkeley S
3、ockets規(guī)范,見規(guī)范,見表 3.1(2)數(shù)據(jù)庫函數(shù))數(shù)據(jù)庫函數(shù)表3.2列出了Winsock規(guī)范定義的數(shù)據(jù)庫查詢例程。其中六個采用getXbyY()的形式,大多要借助網(wǎng)絡上的數(shù)據(jù)庫來獲得信息, (3)WinSock 1.1 擴充了擴充了Berkeley Sockets規(guī)規(guī)范范針對微軟 Windows的特點,WinSock 1.1定義了一批新的庫函數(shù),提供了對于消息驅動機制的支持,有效地利用Windows多任務多線程的機制。見表3.3(4)WinSock 1.1只支持只支持TCP/IP協(xié)議棧協(xié)議棧 2WinSock 2.0WinSock 2.0在源碼和二進制代碼方面與WinSock 1.1兼容
4、,WinSock 2.0增強了許多功能。(1)支持多種協(xié)議(2)引入了重疊I/O的概念(3)使用事件對象異步通知(4)服務的質(zhì)量(QOS)(5)套接口組(6)擴展的字節(jié)順序轉換例程(7)分散/聚集方式I/O (8)新增了許多函數(shù)。 3WinSock 1.1中的阻塞問題中的阻塞問題 阻塞是在把應用程序從Berkeley套接口環(huán)境中移植到Windows環(huán)境中的一個主要焦點。阻塞是指喚起一個函數(shù),該函數(shù)直到相關操作完成時才返回。 在Berkeley套接口模型中,一個套接口的操作的缺省行為是阻塞方式的,除非程序員顯式地請求該操作為非阻塞方式。 在Windows環(huán)境下,我們強烈推薦程序員在盡可能的情況下
5、使用非阻塞方式(異步方式)的操作。因為非阻塞方式的操作能夠更好地在非占先的Windows環(huán)境下工作。 3.1.3 WinSock規(guī)范與規(guī)范與Berkeley套接口的區(qū)別套接口的區(qū)別1套接口數(shù)據(jù)類型和該類型的錯誤返回值套接口數(shù)據(jù)類型和該類型的錯誤返回值 在UNIX中,包括套接口句柄在內(nèi)的所有句柄,都是非負的短整數(shù), 在WinSock規(guī)范中定義了一個新的數(shù)據(jù)類型,稱作SOCKET,用來代表套接字描述符。 typedef u_int SOCKET;SOCKET可以取從0到INVALID_SOCKET-1之間的任意值。2select()函數(shù)和函數(shù)和FD_*宏宏 在Winsock中,使用select()
6、函數(shù)時,應用程序應堅持用FD_XXX宏來設置,初始化,清除和檢查fd_set結構。 3錯誤代碼的獲得錯誤代碼的獲得 在UNIX 套接字規(guī)范中,如果函數(shù)執(zhí)行時發(fā)生了錯誤,會把錯誤代碼放到errno或h_errno變量中。 在Winsock中,錯誤代碼可以使用WSAGetLastError()調(diào)用得到。4指針指針 所有應用程序與Windows Sockets使用的指針都必須是FAR指針。5重命名的函數(shù)重命名的函數(shù)(1)close()改變?yōu)閏losesocket() (2)ioctl()改變?yōu)閕octlsocket() 6Winsock支持的最大套接口數(shù)目支持的最大套接口數(shù)目 在WINSOCK.H中
7、缺省值是64,在編譯時由常量FD_SETSIZE決定。7頭文件頭文件 Berkeley頭文件被包含在WINSOCK.H中。一個Windows Sockets應用程序只需簡單地包含WINSOCK.H就足夠了。8Winsock規(guī)范對于消息驅動機制的支持規(guī)范對于消息驅動機制的支持 體現(xiàn)在異步選擇機制、異步請求函數(shù)、阻塞處理方法、錯誤處理、啟動和終止等方面。 3.2 Winsock 1.1的庫函數(shù)的庫函數(shù)3.2.1 Winsock的注冊與注銷的注冊與注銷1初始化函數(shù)初始化函數(shù)WSAStartup() Winsock 應用程序要做的第一件事,就是必須首先調(diào)用WSAStartup()函數(shù)對Winsock進
8、行初始化。初始化也稱為注冊。注冊成功后,才能調(diào)用其他的Winsock API函數(shù)。(1)WSAStartup()函數(shù)的調(diào)用格式函數(shù)的調(diào)用格式 int WSAStartup( WORD wVersionRequested, LPWSADATA lpWSAData );(2)WSAStartup()函數(shù)的初始化過程函數(shù)的初始化過程 圖3.2說明了初始化的過程 圖3.2 在一臺計算機中,使用同一Windock實現(xiàn)的多個網(wǎng)絡應用程序 (3)WSADATA結構的定義結構的定義#define WSADESCRIPTION_LEN 256#define WSASYS_STATUS_LEN 128typede
9、f struct WSAData WORD wVersion; WORD wHighVersion; char szDescriptionWSADESCRIPTION_LEN+1; char szSystemStatusWSASYS_STATUS_LEN+1; unsigned short iMaxSockets; unsigned short iMaxUdpDg; char * lpVendorInfo; WSADATA; (4)初始化函數(shù)可能返回的錯誤代碼)初始化函數(shù)可能返回的錯誤代碼WSASYSNOTREADY: 網(wǎng)絡通信依賴的網(wǎng)絡子系統(tǒng)沒有準備好。WSAVERNOTSUPPORTED:
10、 找不到所需的Winsock API相應的動態(tài)連接庫。WSAEINVAL: DLL不支持應用程序所需的Winsock版本。WSAEINPROGRESS: 正在執(zhí)行一個阻塞的Winsock 1.1操作。WSAEPROCLIM: 已經(jīng)達到Winsock支持的任務數(shù)上限。 WSAEFAULT: 參數(shù)lpWSAData不是合法指針。 (5)初始化)初始化Winsock的示例的示例#include / 對于Winsock 2.0,應包括 Winsock2.h文件aa() WORD wVersionRequested; / 應用程序所需的Winsock版本號WSADATA wsaData; / 用來返回W
11、insock 實現(xiàn)的細節(jié)信息。Int err; / 出錯代碼。 wVersionRequested =MAKEWORD(1,1); / 生成版本號1.1。err = WSAStartup(wVersionRequested, &wsaData ); / 調(diào)用初始化函數(shù)。if (err!=0 ) return; / / 通知用戶找不到合適的DLL文件。/ 確認返回的版本號是客戶要求的1.1i f ( L O B Y T E ( w s a D a t a . w Ve r s i o n ) ! = 1 | | HYBYTE(wsaData.wVersion )!=1) WSAClean
12、up(); return; /* 至此,可以確認初始化成功,Winsock.DLL可用。 2注銷函數(shù)注銷函數(shù)WSACleanup()當程序使用完Winsock.DLL提供的服務后,應用程序必須調(diào)用WSACleanup()函數(shù),來解除與Winsock.DLL庫的綁定,釋放Winsock實現(xiàn)分配給應用程序的系統(tǒng)資源,中止對Windows Sockets DLL的使用。 int WSACleanup ( void ); 3.2.2 Winsock的錯誤處理函數(shù)的錯誤處理函數(shù)1WSAGetLastError()函數(shù)函數(shù)int WSAGetLastError ( void );本函數(shù)返回本線程進行的上一
13、次Winsock函數(shù)調(diào)用時的錯誤代碼。 2WSASetLastError()函數(shù)函數(shù)void WSASetLastError ( int iError );本函數(shù)允許應用程序為當前線程設置錯誤代碼,并可由后來的WSAGetLastError()調(diào)用返回。3.2.3 主要的主要的Winsock函數(shù)函數(shù)1創(chuàng)建套接口創(chuàng)建套接口SOCKET()SOCKET socket (int af, int type, int protocol);舉例:舉例:SOCKET sockfd=SOCKET( AF_INET, SOCK_STREAM, 0); /* 創(chuàng)建一個流式套接字。SOCKET sockfd=SOC
14、KET( AF_INET, SOCK_DGRAM, 0); /* 創(chuàng)建一個數(shù)據(jù)報套接字。 2將套接口綁定到指定的網(wǎng)絡地址將套接口綁定到指定的網(wǎng)絡地址BIND()int bind( SOCKET s, const struct sockaddr * name, int namelen);相關的三種相關的三種Winsock地址結構地址結構有許多函數(shù)都需要套接字的地址信息,像UNIX 套接字一樣,Winsock也定義了三種關于地址的結構,經(jīng)常使用。通用的Winsock地址結構,針對各種通信域的套接字,存儲它們的地址信息。struct sockaddr u_short sa_family; /* 地址
15、家族char sa_data14; /* 協(xié)議地址 專門針對Internet 通信域的Winsock地址結構struct sockaddr_in short. sin_family; /* 指定地址家族,一定是AF_INET.u_short sin_port; /* 指定將要分配給套接字的傳輸層端口號,struct in_addr sin_addr; /* 指定套接字的主機的IP 地址char sin_zero8; /* 全置為0,是一個填充數(shù)。 專用于存儲IP地址的結構Struct in_addr Union Struct u_char s_b1,s_b2,s_b3,s_b4; S_un_b
16、;Struct u_short s_w1,s_w2; S_un_w;U_long S_addr;在使用Internet域的套接字時,這三個數(shù)據(jù)結構的一般用法是:首先,定義一個Sockaddr_in的結構實例變量,并將它清零。然后,為這個結構的各成員變量賦值,第三步,在調(diào)用BIND()綁定函數(shù)時,將指向這個結構的指針強制轉換為 sockaddr*類型。 舉例:舉例:SOCKET serSock; / 定義了一個SOCKET 類型的變量。sockaddr_in my_addr; / 定義一個Sockaddr_in型的結構實例變量。int err; / 出錯碼。 int slen=sizeof( s
17、ockaddr); / sockaddr 結構的長度。serSock = SOCKET(AF_INET, SOCK_DGRAM,0 ); / 創(chuàng)建數(shù)據(jù)報套接字。memset(my_addr,0); / 將Sockaddr_in的結構實例變量清零。my_addr.sin_family = AF_INET; / 指定通信域是Internet。my_addr.sin_port = htons(21); / 指定端口,將端口號轉換為網(wǎng)絡字節(jié)順序。 /* 指定IP地址,將IP地址轉換為網(wǎng)絡字節(jié)順序。my_addr.sin_addr.s_addr = htonl( INADDR-ANY); /* 將套接字
18、綁定到指定的網(wǎng)絡地址,對&my_addr進行了強制類型轉換。if (BIND(serSock, (LPSOCKADDR )&my_addr, slen) = SOCKET_ERROR )/* 調(diào)用WSAGetLastError()函數(shù),獲取最近一個操作的錯誤代碼。err = WSAGetLastError();/* 以下可以報錯,進行錯誤處理。 3啟動服務器監(jiān)聽客戶端的連接請求啟動服務器監(jiān)聽客戶端的連接請求LISTEN()int listen( SOCKET s, int backlog); 4接收連接請求接收連接請求ACCEPT()SOCKET accept( SOCKET
19、s, struct sockaddr* addr, int* addrlen); 5請求連接請求連接CONNECT()int connect( SOCKET s, struct sockaddr * name, int namelen); 舉例舉例struct sockaddr_in daddr;memset(void *)&daddr,0,sizeof(daddr);daddr.sin_family=AF_INET;daddr.sin_port=htons(8888);daddr.sin_addr.s_addr=inet_addr(133.197.22.4);connect(Clie
20、ntSocket,(struct sockaddr *)&daddr,sizeof(daddr); 6向一個已連接的套接口發(fā)送數(shù)據(jù)向一個已連接的套接口發(fā)送數(shù)據(jù)SEND()int send( SOCKET s, char * buf, int len, int flags); 圖3.3 同步套接字的Send()函數(shù)的執(zhí)行流程 7從一個已連接套接口接收數(shù)據(jù)從一個已連接套接口接收數(shù)據(jù)RECV()int recv( SOCKET s, char * buf, int len, int flags);圖3-4說明了send和recv的作用,套接字緩沖區(qū)與應用進程緩沖區(qū)的關系,以及協(xié)議棧所作的傳送
21、。 圖3.4 Send()和Recv()都是對本地套接字的操作 8按照指定目的地向數(shù)據(jù)報套接字發(fā)送數(shù)據(jù)按照指定目的地向數(shù)據(jù)報套接字發(fā)送數(shù)據(jù)SENDTO()int sendto( SOCKET s, char * buf, int len, int flags, struct sockaddr * to, int tolen); 9接收一個數(shù)據(jù)報并保存源地址,從數(shù)據(jù)報套接字接收數(shù)據(jù)接收一個數(shù)據(jù)報并保存源地址,從數(shù)據(jù)報套接字接收數(shù)據(jù)RECVFORM()int recvfrom( SOCKET s, char * buf, int len, int flags, struct sockaddr* f
22、rom, int* fromlen); 10關閉套接字關閉套接字CLOSESOCKET()int closesocket( SOCKET s); 1 1 禁 止 在 一 個 套 接 口 上 進 行 數(shù) 據(jù) 的 接 收 與 發(fā) 送 禁 止 在 一 個 套 接 口 上 進 行 數(shù) 據(jù) 的 接 收 與 發(fā) 送SHUTDOWN()int shutdown( SOCKET s, int how); 3.2.4 Winsock的輔助函數(shù)的輔助函數(shù)1Winsock中的字節(jié)順序轉換函數(shù)中的字節(jié)順序轉換函數(shù)圖3.5 兩種本機字節(jié)順序。 圖3-5 兩種本機字節(jié)順序 Winsock API特為此設置了四個函數(shù),(1
23、)htonl() 將主機的無符號長整型數(shù)本機順序轉換為網(wǎng)絡字節(jié)順序 (Host to Network Long),用于IP地址。u_long PASCAL FAR htonl( u_long hostlong); hostlong是主機字節(jié)順序表達的32位數(shù)。htonl()返回一個網(wǎng)絡字節(jié)順序的值。(2)htons() 將主機的無符號短整型數(shù)轉換成網(wǎng)絡字節(jié)順序(Host to Network Short),用于端口號。u_short PASCAL FAR htons( u_short hostshort);hostshort:主機字節(jié)順序表達的16位數(shù)。htons()返回一個網(wǎng)絡字節(jié)順序的值。
24、 (3)ntohl()將一個無符號長整型數(shù)從網(wǎng)絡字節(jié)順序轉換為主機字節(jié)順序。(Network to Host Long),用于IP地址。u_long PASCAL FAR ntohl( u_long netlong); netlong是一個以網(wǎng)絡字節(jié)順序表達的32位數(shù),ntohl()返回一個以主機字節(jié)順序表達的數(shù)。(4)ntohs()將一個無符號短整型數(shù)從網(wǎng)絡字節(jié)順序轉換為主機字節(jié)順序。(Network to Host Sort),用于端口號u_short PASCAL FAR ntohs( u_short netshort);netshort是一個以網(wǎng)絡字節(jié)順序表達的16位數(shù)。ntohs()
25、返回一個以主機字節(jié)順序表達的數(shù)。 2獲取與套接口相連的端地址獲取與套接口相連的端地址GETPEERNAME()int getpeername( SOCKET s, struct sockaddr * name, int * namelen); 3獲取一個套接口的本地名字獲取一個套接口的本地名字GETSOCKNAME()int getsockname( SOCKET s, struct sockaddr * name, int * namelen); 4將一個點分十進制形式的將一個點分十進制形式的IP地址轉換成一個長整型數(shù)地址轉換成一個長整型數(shù)INET_ADDR()unsigned long i
26、net_addr (const char * cp); 5 將 網(wǎng) 絡 地 址 轉 換 成 點 分 十 進 制 的 字 符 串 格 式 將 網(wǎng) 絡 地 址 轉 換 成 點 分 十 進 制 的 字 符 串 格 式INET_NTOA()char * inet_ntoa( struct in_addr in); 3.2.5 Winsock的信息查詢函數(shù)的信息查詢函數(shù)Winsock API提供了一組信息查詢函數(shù),讓我們能方便地獲取套接口所需要的網(wǎng)絡地址信息以及其它信息, (1)Gethostname()用來返回本地計算機的標準主機名。int gethostname(char* name, int na
27、melen);(2)Gethostbyname()返回對應于給定主機名的主機信息。struct hostent* gethostbyname(const char* name); (3)Gethostbyaddr()根據(jù)一個IP地址取回相應的主機信息。struct hostent* gethostbyaddr(const char* addr, int len, int type);(4)Getservbyname()返回對應于給定服務名和協(xié)議名的相關服務信息。struct servent* getservbyname(const char* name, const char* proto);
28、(5)Getservbyport()返回對應于給定端口號和協(xié)議名的相關服務信息。struct servent * getservbyport(int port,const char *proto); (6)Getprotobyname()返回對應于給定協(xié)議名的相關協(xié)議信息。struct protoent * getprotobyname(const char * name);(7)Getprotobynumber ()返回對應于給定協(xié)議號的相關協(xié)議信息。struct protoent * getprotobynumber(int number); 除了Gethostname()函數(shù)以外,其它六
29、個函數(shù)有以下共同的特點:函數(shù)名都采用GetXbyY的形式。 如果函數(shù)成功地執(zhí)行,就返回一個指向某種結構的指針,該結構包含所需要的信息。如果函數(shù)執(zhí)行發(fā)生錯誤,就返回一個空指針。應用程序可以立即調(diào)用WSAGetLastError()來得到一個特定的錯誤代碼。函數(shù)執(zhí)行時,可能在本地計算機上查詢,也可能通過網(wǎng)絡向域名服務器發(fā)送請求,來獲得所需要的信息,這取決于用戶網(wǎng)絡的配置方式。為了能讓程序在等待響應時能作其他的事情,Winsock API擴充了一組作用相同的異步查詢函數(shù),不會引起進程的阻塞。并且可以使用Windows的消息驅動機制。也是六個函數(shù),與GetXbyY各函數(shù)對應,在每個函數(shù)名前面加上了WS
30、AAsync前綴,名字采用WSAAsyncGetXByY()的形式。它們的工作機制在后面詳述3.2.6 WSAAsyncGetXByY類型的擴展函數(shù)類型的擴展函數(shù)WSAAsyncGetXByY類型的擴展函數(shù)是GetXByY函數(shù)的異步版本,這些函數(shù)可以很好地利用Windows的消息驅動機制。1WSAAsyncGetHostByName()函數(shù)函數(shù)HANDLE WSAAsyncGetHostByName ( HWND hWnd, unsigned int wMsg,const char * name, char * buf, int buflen ); 2WSAAsyncGetHostByAddr()函數(shù)函數(shù)HANDLE WSAAsyncGetHostByAddr ( HWND hWnd, unsigned int wMsg, const char * addr, int len, int type, char * buf, int buflen ); 3WSAAsyncGetServByName()函數(shù)函數(shù)HANDLE WSAAsyncGetServByName ( HWND hWnd, unsigned int wMsg,const char * name, const ch
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 小區(qū)兩間門面租賃合同
- 單位向私人借款合同書
- 國際空運運輸代理合同
- 風險管理與應對策略制定作業(yè)指導書
- 2025年泰安考從業(yè)資格證貨運試題
- 小學三年級,五年級下冊數(shù)學口算題比賽試卷
- 小學二年級數(shù)學萬以內(nèi)口算題
- 2025年北京交通運輸從業(yè)資格證怎樣考試
- 2025年西藏貨運從業(yè)資格證模擬考試系統(tǒng)
- 2025年烏蘭察布下載貨運從業(yè)資格證模擬考試題
- 2024年同等學力人員申請碩士學位英語試卷與參考答案
- 臨床用血管理培訓
- 介入手術室護理風險
- 小學一年級數(shù)學20以內(nèi)的口算題(可直接打印A4)
- 春季安全行車教育培訓
- 2024年6月第3套英語六級真題
- 2024年江蘇省公務員錄用考試《行測》題(A類)
- 2024年10月時政100題(附答案)
- 江蘇省無錫市2024年中考數(shù)學試卷(含答案)
- 2024年保密知識測試試題及答案(奪冠)
- 北師大版八年級下冊因式分解(分組分解法)100題及答案
評論
0/150
提交評論