網(wǎng)絡程序設計入門_第1頁
網(wǎng)絡程序設計入門_第2頁
網(wǎng)絡程序設計入門_第3頁
網(wǎng)絡程序設計入門_第4頁
網(wǎng)絡程序設計入門_第5頁
已閱讀5頁,還剩49頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、人民郵電出版社 第7章 網(wǎng)絡程序設計入門8/25/202217.1有關網(wǎng)絡程序設計的一些概念7.1.1什么是網(wǎng)絡應用軟件?人們常將應用軟件分為單機版的和網(wǎng)絡版,單機版應用軟件就是一般程序設計語言教科書重點講述的,在單機環(huán)境下使用的軟件,這種軟件的特點是結構簡單,易于學習與設計。另一種應用軟件是需要安裝在網(wǎng)絡環(huán)境中使用的,網(wǎng)絡中不同主機上安裝的軟件需要進行相互通信才能完成其功能,這就是網(wǎng)絡應用軟件,這種軟件的特點是結構較為復雜,軟件設計者不但要掌握程序設計的一般知識,還要掌握網(wǎng)絡系統(tǒng)的有關知識與理解網(wǎng)絡通信協(xié)議。由于計算機網(wǎng)絡的廣泛應用,目前軟件開發(fā)的主流是設計這類網(wǎng)絡環(huán)境下的應用軟件。7.1有

2、關網(wǎng)絡程序設計的一些概念7.1.2網(wǎng)絡中兩個通信程序如何相互識別對方在操作系統(tǒng)中我們知道,同一個系統(tǒng)中不同的兩個進程間進行通信時,通過系統(tǒng)分配的進程號(process ID)就可以惟一標識一個進程,也就是說兩個相互通信的進程,只要知道知識對方的進程號就可以進行通信。而網(wǎng)絡情況下進程間的通信問題,就要復雜得多,不能只簡單的用進程號來標識不同的進程。首先要解決如何識別網(wǎng)絡中不同的主機問題,其次因為各個主機系統(tǒng)中都獨立地進行進程號分配,并且不同系統(tǒng)中進程號的產(chǎn)生與分配策略也不同,所以在網(wǎng)絡環(huán)境中不能再通過進程號來簡單的識別兩個相互通信的進程了。那么,在網(wǎng)絡環(huán)境中,兩個相互通信的進程,如何識別對方呢?

3、7.1有關網(wǎng)絡程序設計的一些概念7.1.2網(wǎng)絡中兩個通信程序如何相互識別對方在網(wǎng)絡中為了標識通信的進程,首先要標識網(wǎng)絡中進程所在的主機,其次要標識主機上不同的進程。關于網(wǎng)絡環(huán)境下不同主機的識別問題,在講傳輸層協(xié)議時,我們知道為了完成端到端進程之間的通信,在互聯(lián)網(wǎng)中使用IP地址來標識不同的主機。關于主機上不同的進程問題,在前面講端口號時已經(jīng)說明過,在網(wǎng)絡協(xié)議中使用端口號來標識主機上的不同進程。還有一個問題,就是前面我們討論的都是在TCP/IP協(xié)議下,端到端進程的標識問題,其實網(wǎng)絡應用程序由于不同的主機可能使用不同的網(wǎng)絡協(xié)議,其工作方式不同,地址的表示格式也不同,因此,網(wǎng)絡中進程的通信還要解決多種

4、協(xié)議的識別問題。這樣為了惟一的標識網(wǎng)絡中通信的一個進程(即通信的某一方)就要使用一個如下的三元組:(本地協(xié)議,本地IP地址,本地端口號)7.1有關網(wǎng)絡程序設計的一些概念7.1.2網(wǎng)絡中兩個通信程序如何相互識別對方這樣一個三元組由于它只指定了通信時一條連接的半個部分,即通信的一方,所以叫一個半相關(half-association)。如果要完整的表示網(wǎng)絡中進行通信的兩個進程,那么就要使用一個如下結構的六元組:(本地協(xié)議,本地地址,本地端口號,遠地協(xié)議,遠地地址,遠地端口號)7.1有關網(wǎng)絡程序設計的一些概念7.1.2網(wǎng)絡中兩個通信程序如何相互識別對方下面我們仔細分析一下這樣一個六元組,在互聯(lián)網(wǎng)中通

5、信的兩臺主機在網(wǎng)絡層都只能使用IP協(xié)議,但在網(wǎng)絡層之上可以選擇使用TCP協(xié)議或UDP協(xié)議。這樣就可能得到以下四種類型的相關六元組:(本地TCP協(xié)議,本地IP地址,本地端口號,遠程TCP協(xié)議,遠程IP地址,遠程端口號)(本地UDP協(xié)議,本地IP地址,本地端口號,遠程UDP協(xié)議,遠程IP地址,遠程端口號)(本地TCP協(xié)議,本地IP地址,本地端口號,遠程UDP協(xié)議,遠程IP地址,遠程端口號)(本地UDP協(xié)議,本地IP地址,本地端口號,遠程TCP協(xié)議,遠程IP地址,遠程端口號)7.1有關網(wǎng)絡程序設計的一些概念7.1.2網(wǎng)絡中兩個通信程序如何相互識別對方如果通信的兩端使用不同的協(xié)議,即上面第3和第4種情

6、況,根據(jù)前面我們所學的知識,由于TCP協(xié)議和UDP協(xié)議使用的協(xié)議格式大不相同,因此通信時雙方在傳輸層不能相互識別對方送來的數(shù)據(jù),也就不可能進行正常的通信,因此上面說的后兩種情況是不存在的。換句話說,通信的兩個進程在端到端的傳輸層只能使用相同的協(xié)議,因此一個完整的主機間的通信,可以簡單的用一個五元組來標識通信的兩個進程:(協(xié)議,本地IP地址,本地端口號,遠程IP地址,遠程端口號)綜上所述,這樣一個五元組可以惟一標識網(wǎng)絡中兩個通信的進程或一條連接,因此叫做一個相關(association)。為了在進程間進行正確的通信,只有兩個協(xié)議相同的半相關才能組合成一個可用的相關。7.1有關網(wǎng)絡程序設計的一些概

7、念7.1.3Windows Sockets介紹1.Windows Sockets的概念Windows Sockets顧名思義,它就是在Windows環(huán)境下使用的一套網(wǎng)絡編程機制(或規(guī)范),常常簡稱為Winsock。該規(guī)范是在上個世紀90年代初制定的。這套規(guī)范是在Windows操作系統(tǒng)下得到廣泛應用的、開放的、支持多種協(xié)議的網(wǎng)絡編程接口。該規(guī)范從1991年的1.0版到1997年的2.2.1版,經(jīng)過不斷完善并在Intel、Microsoft、Sun、SGI、Informix、Novell等公司的大力支持下,現(xiàn)在已經(jīng)成為Windows環(huán)境下網(wǎng)絡編程事實上的標準。7.1有關網(wǎng)絡程序設計的一些概念7.1

8、.3Windows Sockets介紹2.Windows Sockets的來源Sockets本來是UNIX操作系統(tǒng)下流行的一種網(wǎng)絡編程接口(API),它是1983年在Berkeley(加州大學伯克利分校)4.2 BSD操作系統(tǒng)中被首先引入的,因此被稱為“Berkeley Socket API”。在剛開始時它只支持TCP/IP協(xié)議,后來在4.3 BSD操作系統(tǒng)中增加了對國際標準化組織ISO制定的開放系統(tǒng)互聯(lián)參考模型OSI網(wǎng)絡協(xié)議的支持。由于BSD操作系統(tǒng)做為一種主流的UNIX操作系統(tǒng)被廣泛使用,因此“Berkeley Socket API”這個模型就成了TCP/IP網(wǎng)絡的編程接口標準。從4.2

9、BSD開始,Berkeley套接口API在不斷地完善和發(fā)展,一直到1995年的4.4 BSD-Lite2為止。Windows網(wǎng)絡應用程序編程接口Windows Sockets API就是在1991年根據(jù)4.3 BSD操作系統(tǒng)的“Berkeley Socket API”制定的。7.1有關網(wǎng)絡程序設計的一些概念7.1.3Windows Sockets介紹3.Windows Sockets的版本目前常用的Winsock有兩個版本:一個是16位的Winsock 1.1,由動態(tài)鏈接庫WINSOCK.DLL提供支持;另一個是32位的Winsock 2.2,由動態(tài)鏈接庫WSOCK32.DLL提供支持。前者主

10、要用在Windows早期的版本中,如Windows 95等版本中,后者主要用在Windows2000和Windows XP等版本中。另外說明一下,本書所講的Windows下TCP/IP編程接口為Winsock 2.2,與低版本的Winsock 1.1相比它主要是擴充了對其它協(xié)議(如IPX、NETBIOS等)的支持。由于Winsock 2.2與Winsock 1.1規(guī)格中所有的函數(shù)調用完全兼容,所以低版本的Winsock應用程序在Winsock 2庫加載的情況下也能夠正常運行。7.1有關網(wǎng)絡程序設計的一些概念7.1.3Windows Sockets介紹4.Winsock API函數(shù)的分類在Win

11、sock規(guī)范中把Winsock API函數(shù)集分為與BSD Socket(用在UNIX中)相兼容的基本函數(shù)、網(wǎng)絡數(shù)據(jù)信息檢索函數(shù)和Windows專用擴展函數(shù)三類。由此可以看出,Winsock來源于BSD Socket API,但它又根據(jù)Windows操作系統(tǒng)的特點進行了擴充。因此,Winsock規(guī)范的核心內容是符合Berkeley Socket風格的庫函數(shù),但為了使程序員能充分地利用Windows消息驅動機制進行編程,也定義開發(fā)了一組針對Windows的擴展庫函數(shù)。這份規(guī)范定義了應用程序開發(fā)者能夠使用,并且網(wǎng)絡軟件供應商能夠實現(xiàn)的一套庫函數(shù)調用和相關語義。7.1有關網(wǎng)絡程序設計的一些概念7.1.

12、3Windows Sockets介紹5.Windows Sockets對多線程的支持Windows Sockets支持多線程的Windows進程。一個進程可以包含一個(在Windows 3.1非多線程版本中,一個任務對應了一個僅具有單個線程的進程)或多個同時執(zhí)行的線程。7.1有關網(wǎng)絡程序設計的一些概念7.1.4套接口的概念Windows Sockets API依靠套接口(Socket)進行通訊,那么什么是套接口(Socket)呢?對于初學網(wǎng)絡程序設計的人們來說,套接口是一個既抽象且又很重要的概念。因此要注意對于套接口這個概念的理解與體會。套接口可以看成是兩個網(wǎng)絡應用程序進行通信時,各自通信連接

13、中的一個端點,這個端點是一個邏輯上的概念。通信時其中的一個網(wǎng)絡應用程序將要傳輸?shù)囊欢涡畔懭胨谥鳈C的Socket中,該Socket通過與網(wǎng)絡接口卡(Network Interface Cards, NIC)相連的傳輸介質將這段信息發(fā)送到另外一臺主機的Socket中,使這段信息能傳送到其他程序中,如圖7-1所示。7.1有關網(wǎng)絡程序設計的一些概念程序A程序B主機A主機B網(wǎng)絡接口卡(NIC)基于TCP/IP的網(wǎng)絡網(wǎng)絡管理軟件SocketSocket圖7-1套接口通信工作原理圖7.1有關網(wǎng)絡程序設計的一些概念為了滿足不同的通信程序對通信質量和性能的要求,一般的網(wǎng)絡系統(tǒng)提供了三種不同類型的套接口,以

14、供用戶在設計網(wǎng)絡應用程序時根據(jù)不同的要求來選擇。這三種套接口分別是:流式套接口(SOCK_STREAM):它提供了一種可靠的、面向連接的雙向數(shù)據(jù)傳輸服務。實現(xiàn)了數(shù)據(jù)的無差錯、無重復地發(fā)送。內設流量控制,被傳輸?shù)臄?shù)據(jù)看作是無記錄邊界的字節(jié)流。在TCP/IP協(xié)議族中,使用TCP協(xié)議來實現(xiàn)字節(jié)流的傳輸,當用戶想要發(fā)送大批量的數(shù)據(jù),或者對數(shù)據(jù)的傳輸有較高的要求時使用流式套接口。7.1有關網(wǎng)絡程序設計的一些概念數(shù)據(jù)報套接口(SOCK_DGRAM):它提供了一種無連接、不可靠的雙向數(shù)據(jù)傳輸服務。數(shù)據(jù)包以獨立的包形式被發(fā)送,并且保留了記錄邊界,不提供可靠性保證。數(shù)據(jù)在傳輸過程中可能會丟失或重復,并且不能保證

15、在接收端數(shù)據(jù)按發(fā)送順序接收。在TCP/IP協(xié)議族,使用UDP協(xié)議(Winsock 2也支持其它的協(xié)議)來實現(xiàn)數(shù)據(jù)報套接口。在同一臺計算機上或負載較輕的LAN上,因為出現(xiàn)差錯的可能性較小,可以使用數(shù)據(jù)報套接口進行數(shù)據(jù)傳輸,這樣通信的質量可以得到保證,并且通信的效率較高。另外,在前面的章節(jié)中我們已經(jīng)說過,UDP還可以實現(xiàn)廣播通信。原始套接口(SOCK_RAW):該套接口允許對較低層協(xié)議(如IP或ICMP)進行直接訪問。常用于檢驗新的網(wǎng)絡協(xié)議實現(xiàn),也可用于測試新配置或安裝的網(wǎng)絡設備。要說明的是Windows Sockets規(guī)范并沒有規(guī)定Windows Sockets DLL必須支持原始套接口。套接口

16、在編程時對于用戶來說是可見的,應用程序一般僅在同一類型的套接口間通訊。不過只要底層的通訊協(xié)議允許,不同類型的套接口間也照樣可以通訊(一般很少這樣做)。7.1有關網(wǎng)絡程序設計的一些概念7.1.5套接口編程原理為了便于讀者理解套接口的工作機制,我們舉一個日常生活中的例子。電話服務系統(tǒng)與面向連接的套接口機制非常相似。電信局提供的普通電話服務(比如114提供查號服務功能)類似于服務器(Server),普通電話用戶類似于客戶(Client)。比如有客戶要查某單位的電話號碼,于是就開始了一次查號的通信過程,該過程可以分為以下幾個階段(對于下面提到的函數(shù),只要知道其大概的含義就可以了,在后面將要專門介紹這些

17、函數(shù)的用法):首先電信局必須要有一個電話總機,相當于套接口通信機制中提供服務的服務器,在Socket中通過調用socket()函數(shù)來開啟一個服務,也就是說要創(chuàng)建一個提供服務的套接口。7.1有關網(wǎng)絡程序設計的一些概念7.1.5套接口編程原理電信局必須給電話總機分配一個號碼(如114,意思是查號服務的號碼是114),以便用戶通過撥該號碼得到電話服務,同時接入該電信局的用戶必須知道該總機的號碼。同樣,在服務器端也要為啟動的服務指定一端口號,并且要連接到該服務器的客戶必須要知道該端口號(如客戶要查詢電話號碼時,必須要知道查號臺是114)。這在Socket中通過調用bind()函數(shù)把一個端口與一個特寫服

18、務聯(lián)系起來(叫綁定)。電信局的114查號臺下會開設一些自動服務的分機,但是它們的數(shù)量是有限的。總機開通后就一直在監(jiān)聽(listen)用戶的撥號,用戶撥打114時,可能撥通,得到服務;也可能撥不通,就會聽到忙音。同樣地,我們在建立一個socket服務時,也會調用listen()函數(shù)來監(jiān)聽客戶的請求。7.1有關網(wǎng)絡程序設計的一些概念7.1.5套接口編程原理對于用戶來說,如果知道電信局的查號號碼,在想得到查號服務時就可以撥打114,請求得到電信局的服務,這相當于在客戶端要進行的操作。同樣在Socket通信中,在客戶端也要先用socket()函數(shù)建立一個請求服務的套接口,然后調connect()函數(shù)進

19、行連接與服務器進行連接。當然和電話一樣,用戶可能連通得到服務,也可連不通,請求的服務失敗。電信局的總機接受了某用戶撥打的電話后,負責把用戶與一個分機連通,而總機本身則又回到等待的狀態(tài),以等待其它客戶的請求。在Socket通信中這個相當于服務器調用accept()函數(shù)進入監(jiān)聽處理過程。服務器端建立一個新的套接口來對此連接提供服務,而原先的套接口則又回到監(jiān)聽狀態(tài),等待新客戶的請求。服務器與客戶之間通信時,使用recv()函數(shù)接收套接口數(shù)據(jù),使用send()函數(shù)向套接口發(fā)送數(shù)據(jù)。7.1有關網(wǎng)絡程序設計的一些概念7.1.5套接口編程原理服務完成后,掛上電話,線路斷開,一次服務過程結束,不然的話則該線路

20、一直被占用,浪費了通信資源。在服務器和客戶之間,最后也要使用closesocket()函數(shù)關閉套接口,釋放該套接口上的有關資源,這可以由通信的任何一方或雙方同時提出。上面提到的Winsock API函數(shù)是使用套接口編程時所使用的最基本的一些函數(shù),幾乎每一個使用套接口編程的網(wǎng)絡應用程序都要使用這些函數(shù),后面我們將詳細介紹這些函數(shù)的功能和用法。用戶編寫網(wǎng)絡應用程序時,錯誤的出現(xiàn)是不能可避免的,因此對錯誤的檢查和控制是至關重要的,一個好的或者說成功的Winsock應用程序應該盡可能地檢測和處理各種錯誤。由于下面我們接觸到的所有函數(shù)都有調用成功與不成功兩種情況,因此,我們打算先為大家介紹Winsock

21、中錯誤檢查和控制的方法。7.1有關網(wǎng)絡程序設計的一些概念7.1.5套接口編程原理對Winsock函數(shù)來說,返回錯誤是非常常見的。與大多數(shù)系統(tǒng)調用類似,Winsock函數(shù)發(fā)生的錯誤也有兩種。多數(shù)情況下發(fā)生的錯誤都是無關緊要的,通信仍可在套接口上進行,但有些錯誤是致命性的,使應用程序無法繼續(xù)執(zhí)行。不成功的Winsock函數(shù)調用返回的最常見的值是宏定義SOCKET_ERROR,在Winsock的頭文件中(如Winsock 2.h),它的數(shù)值是-1。實際上,如果調用一個Winsock函數(shù)時,發(fā)生了錯誤,我們應該進一步使用WSAGetLastError()函數(shù),以獲得對這一錯誤詳細的說明,該函數(shù)的使用非

22、常簡單,它的格式如下:int WSAGetLastError ( void );7.1有關網(wǎng)絡程序設計的一些概念7.1.6網(wǎng)絡字節(jié)順序不同的主機對字節(jié)值的存儲順序不同。在存儲由多個字節(jié)組成的一個字時,有的計算機在起始地址處存放低整數(shù)的低序號字節(jié),這種存儲格式叫“小序在前”(little-endian)。而有的計算機在起始地址處存放整數(shù)的高序號字節(jié),這種存儲格式叫“大序在前”(big-endian)。每種計算機究竟采用那種字節(jié)存儲順序由各自的設計決定,如Windows系列的操作系統(tǒng)使用的是小序在前的存儲方式,而Sun OS和Solaris等采用的大序在前的存儲方式。在計算機中,TCP/IP協(xié)議使

23、用的16位整數(shù)(如端口號)和32位整數(shù)(如IP地址)是按計算機各自的“主機字節(jié)”(host-byte)來表示的。在網(wǎng)絡中,為了保證數(shù)據(jù)的正確性,在網(wǎng)絡通信協(xié)議中必須指定網(wǎng)絡字節(jié)順序。如果在網(wǎng)絡中使用IP地址和端口號,按“互聯(lián)網(wǎng)聯(lián)網(wǎng)標準”的要求,指定的多字節(jié)值必須用“大序在前”的形式來表示,一般稱之為“網(wǎng)絡字節(jié)”(network-byte)順序。7.1有關網(wǎng)絡程序設計的一些概念7.1.6網(wǎng)絡字節(jié)順序在Winsock中有一系列的函數(shù)可用于多字節(jié)數(shù)的轉換,把它們從主機字節(jié)順序轉換成網(wǎng)絡字節(jié)順序,反之亦然。下面四個API函數(shù)便將一個數(shù)從主機字節(jié)順序轉換成網(wǎng)絡字節(jié)順序:htonl():參數(shù)是主機字節(jié)順序

24、的一個4字節(jié)數(shù),函數(shù)返回網(wǎng)絡字節(jié)順序的數(shù)。WSAHtonl)():參數(shù)是主機字節(jié)順序的一個4字節(jié)數(shù),函數(shù)返回網(wǎng)絡字節(jié)順序的數(shù)。htons():參數(shù)是主機字節(jié)順序的一個2字節(jié)數(shù),函數(shù)返回網(wǎng)絡字節(jié)順序的數(shù)。WSAHtons():參數(shù)是主機字節(jié)順序的一個2字節(jié)數(shù),函數(shù)返回網(wǎng)絡字節(jié)順序的數(shù)。7.2網(wǎng)絡程序工作模型 7.2.1網(wǎng)絡程序要考慮的幾個問題網(wǎng)絡程序與單機環(huán)境下運行的程序有較大的區(qū)別,程序員在設計網(wǎng)絡程序時應該了解與注意這些問題,才能設計出高質量的網(wǎng)絡應用程序。1.并發(fā)環(huán)境下的網(wǎng)絡編程我們常用的操作系統(tǒng)Windows和Linux等都支持多進程(或線程)的并發(fā)執(zhí)行,多進程應用程序,由于涉及到資源共

25、享、進程之間的同步等問題,其編程要比單進程環(huán)境復雜得多。7.2網(wǎng)絡程序工作模型 7.2.1網(wǎng)絡程序要考慮的幾個問題在多進程編程環(huán)境中,使用的系統(tǒng)調用或函數(shù)必須是可重入的。哪些系統(tǒng)調用或系統(tǒng)函數(shù)是可重入的,這在不同的系統(tǒng)中是不同的。一般的系統(tǒng)都會對其進行詳細說明。在多線程應用中,對系統(tǒng)調用或函數(shù)的使用有很多限制,因此在編程時應該注意的是對于那些不可重入的調用或函數(shù),系統(tǒng)如果不提供多線程安全的版本,則應用編程人員需要避免使用或自己編寫相應的函數(shù)。例如在Solaris操作系統(tǒng)中,在一個線程中關閉另一個線程下在使用的網(wǎng)絡端口會導致應用程序“死掉”,而這種情況在Digiatl Unix中則不會出現(xiàn)。7.

26、2網(wǎng)絡程序工作模型 7.2.1網(wǎng)絡程序要考慮的幾個問題2.異構環(huán)境下的網(wǎng)絡編程在網(wǎng)絡中,通常在異構環(huán)境下進行程序之間的通信。因此網(wǎng)絡程序必須要考慮不同平臺之間的異構性,這種異構性主要表現(xiàn)在不同平臺上數(shù)據(jù)表示格式的差異性上,這種差異性主要表現(xiàn)在以下幾個方面:(1)字節(jié)順序即前一節(jié)介紹的網(wǎng)絡字節(jié)順序。作為程序員必須要清楚所用系統(tǒng)的字節(jié)順序。在網(wǎng)絡應用程序中,傳輸?shù)耐ㄐ艛?shù)據(jù)主要包含兩個部分,一部分是分組中協(xié)議的首部,另一個部分是程序中要使用的數(shù)據(jù)。這兩個部分數(shù)據(jù)都要考慮字節(jié)順序問題。(2)字的長度不同的系統(tǒng)中,對于相同的數(shù)據(jù)類型可能用不同的長度表示。例如在64位的操作系統(tǒng)中和32位的操作系統(tǒng)中對于l

27、ong int類型的長度表示是不一樣的。7.2網(wǎng)絡程序工作模型 7.2.1網(wǎng)絡程序要考慮的幾個問題(3)字節(jié)定界問題不同的平臺上給結構(struct)或聯(lián)合(union)打包的方式也是不同的,這取決于所用數(shù)據(jù)類型的位數(shù)及機器的定界限制。一般情況下,操作系統(tǒng)在分配內存時,數(shù)據(jù)結構以4字節(jié)定界。例如,在很多系統(tǒng)中,默認情況下結構structchar a; int b的長度為8而不是5。只有在1字節(jié)定界的情況下其長度才為5。對于字節(jié)的定界問題,對于具有相同字節(jié)順序的平臺,通信雙方均經(jīng)單字節(jié)定界,對于具不同字節(jié)順序的平臺間通信,可以顯式的定義其格式(位數(shù)、字節(jié)順序類型),也可以將需要發(fā)送信息的結構變換

28、成一種統(tǒng)一的格式(如轉換成一個字符數(shù)組),到達接收方后再執(zhí)行相反的轉換過程。對于數(shù)據(jù)結構中有比特變量的情況,處理起來比較復雜,因此建議在實際網(wǎng)絡編程中,盡量不要使用比特類型的變量。另外要注意,在很多網(wǎng)絡協(xié)議的設計中,常常需要填充一些無用的字節(jié),以滿足4字節(jié)定位的要求,從而簡化協(xié)議的實現(xiàn)。7.2網(wǎng)絡程序工作模型 7.2.1網(wǎng)絡程序要考慮的幾個問題3.阻塞與非阻塞通信在網(wǎng)絡編程中,可以將通信分為阻塞與非阻塞兩種模式。在進行網(wǎng)絡編程時,選擇通信模式也是一件很重要的事情。對于不同的協(xié)議,阻塞通信和非阻塞通信有不同的表現(xiàn)。以套接口編程為例,在阻塞模式下,利用TCP協(xié)議發(fā)送一個報文時,如果低層協(xié)議沒有可用

29、空間來存放用戶數(shù)據(jù),則應用進程將阻塞(即進行等待),直到有可用的空間。而在非阻塞模式下,調用將直接返回而不需要等待。在應用進程調用接收函數(shù)接收報文時,如果是在阻塞模式下,若沒有到達的數(shù)據(jù),則調用將一直阻塞直到有數(shù)據(jù)到達或出錯為止,而在非阻塞模式下,將直接返回而不需要等待。對于UDP協(xié)議而言,因為UDP沒有發(fā)送緩沖,所有UDP協(xié)議即使在阻塞模式下也不會發(fā)生阻塞。7.2網(wǎng)絡程序工作模型 7.2.1網(wǎng)絡程序要考慮的幾個問題對于面向連接的協(xié)議,在連接建立階段,阻塞與非阻塞也表現(xiàn)不一樣。在阻塞模式下,如果沒有連接請求到達,則等待連接調用將阻塞直到有請求到達;但在非阻塞模式下,如果沒有連接請求到達,等待連

30、接調用將直接返回。在連接建立階段,不管是阻塞還是非阻塞模式,發(fā)起連接請求的一方總是會使調用它的進程阻塞,阻塞間隔最少等于到達服務器的一次往返時間。通信模式對應用程序的設計方法也有直接的影響。在非阻塞模式下,應用程序不斷地輪詢查看是否有數(shù)據(jù)到達或有連接請求到達。這種輪詢方式比其他技術耗費更多的CPU時間,因此要盡量避免使用這種技術。而在阻塞模式下。不存在這一問題。但是阻塞模式的缺點是進程在執(zhí)行I/O操作時將被阻塞而不能執(zhí)行其他的工作,因此在單進程或單線程應用中不能使用這種模式。在多線程應用中比較適合采用阻塞模式,一個線程被阻塞不影響其他線程的工作。7.2網(wǎng)絡程序工作模型 7.2.1網(wǎng)絡程序要考慮

31、的幾個問題另外,通信模式的選擇與操作系統(tǒng)的類型也有關系,例如在非搶占式的Windows操作系統(tǒng)中,應用程序應盡量不要使用阻塞模式工作。4.服務類型的選擇從通信的角度來說,網(wǎng)絡協(xié)議棧中的各層所提供的服務可以分為兩大類:面向連接服務與無連接服務。對于面向連接的通信,由于兩個對等實體為進行數(shù)據(jù)通信要建立連接。面向連接服務的要求是:在數(shù)據(jù)交換之前,必須先建立連接;當數(shù)據(jù)交換結束后,則應該終止這個連接。例如,我們前面已經(jīng)介紹過,在TCP/IP協(xié)議棧中,TCP協(xié)議提供的就是這種面向連接的服務。對于在一段時間間隔內,要向同一目的地發(fā)送許多提出報文的情況,就適合使用面向連接的服務。7.2網(wǎng)絡程序工作模型 7.

32、2.2網(wǎng)絡程序工作模型使用TCP/IP協(xié)議的網(wǎng)絡,其協(xié)議核心內容在層次結構的低三層,即網(wǎng)絡接口層、IP層和傳輸層,而這三層的功能一般是由操作系統(tǒng)內核來實現(xiàn)的。操作系統(tǒng)為了保證其安全性和可靠性,其內核部分一般是不能由用戶直接進行操作和使用的,但這并不等于說用戶就不能在其應用程序中使用TCP/IP了。那么用戶如何在網(wǎng)絡應用程序中使用中TCP/IP協(xié)議呢?很顯然,同操作系統(tǒng)提供的其它功能一樣,用戶雖然不能直接使用操作系統(tǒng)的內核,但操作系統(tǒng)給用戶提供了使用內核功能的接口,用戶就可以通過系統(tǒng)功能調用等方式間接的使用這些功能。同樣,用戶可以通過系統(tǒng)提供的網(wǎng)絡應用程序編程接口使用TCP/IP。如圖7-2所示

33、的是兩臺主機通過網(wǎng)絡編程接口,進程間進行通信的原理圖。7.2網(wǎng)絡程序工作模型 7.2.2網(wǎng)絡程序工作模型網(wǎng)絡應用程序編程接口客戶應用程序服務器應用程序圖7-2TCP/IP應用程序工作模型TCP/IP核心協(xié)議物理傳輸介質物理傳輸介質TCP/IP核心協(xié)議網(wǎng)絡應用程序編程接口7.2網(wǎng)絡程序工作模型 7.2.2網(wǎng)絡程序工作模型圖7-2所示的是使用TCP/IP協(xié)議網(wǎng)絡的典型應用方式,即客戶-服務器模式(見7.3節(jié)內容)。除物理傳輸介質外,其它的各對等層之間都要進行虛通信,所以圖7-2中用虛線表示。從圖7-2中還可以看出,程序員不直接面對網(wǎng)絡協(xié)議進行編程,但它通過網(wǎng)絡應用程序編程接口間接的使用了網(wǎng)絡協(xié)議各

34、層提供的服務。這樣做的好處除了可以保證系統(tǒng)的安全可靠性外,還可以簡化網(wǎng)絡應用程序的開發(fā)。通過圖7-2用戶還要明白一個問題,網(wǎng)絡程序設計其實是使用系統(tǒng)提供的網(wǎng)絡協(xié)議完成用戶程序的功能,也就是說在我們的網(wǎng)絡應用程序中如何去使用網(wǎng)絡協(xié)議提供的服務,而不是讓用戶去實現(xiàn)網(wǎng)絡協(xié)議各層的功能。綜上所述,用戶在進行TCP/IP程序設計時,最關鍵的問題是要熟悉所用平臺提供的網(wǎng)絡編程界面(網(wǎng)絡編程API)。在Windows環(huán)境下的網(wǎng)絡應用程序編程接口叫Windows Sockets,其Socket在中文資料中的譯名有好幾種,如“接口”、“插口”、“套接口”等,本書中使用各種資料中較為常用的“套接口”。7.3一個簡

35、單的客戶機/服務器程序編寫一個服務器端程序,該程序的功能是只要有客戶提出請求連接,服務器就接受連接,在連接成功后,服務器就向請求連接的客戶發(fā)送“Hello! I am a server.”的信息。如果服務器向客戶機正確發(fā)送了上述信息,則在服務器端顯示客戶機的IP地址和端口號,并輸出所發(fā)送的字節(jié)數(shù)。編寫一個客戶端程序,該程序的功能是向服務器發(fā)出連接請求,在連接成功后,接收并顯示從服務器收到的信息。該程序中通信協(xié)議使用的是面向連接的TCP協(xié)議(SOCK_STREAM,該內容在第8章中要詳細介紹,在這里讀者只要了解該知識就可以了)。7.4Winsock中建立連接的函數(shù)及其應用7.4.1 加載協(xié)議棧(

36、WSAStartup)在使用Winsock API編制網(wǎng)絡應用程序時,要使用大量系統(tǒng)已經(jīng)實現(xiàn)的網(wǎng)絡功能函數(shù),在調用任何一個Winsock API函數(shù)之前,都必須先檢查協(xié)議棧的安裝情況,也就是檢查系統(tǒng)中是否有Windows Sockets的實現(xiàn)庫。通過調用WSAStartup()函數(shù)便可檢測系統(tǒng)中有沒有一個或多個Windows Sockets的實現(xiàn),本函數(shù)必須是應用程序或DLL調用的第一個Windows Sockets函數(shù),它允許應用程序或DLL指明Windows Sockets API的版本號及獲得特定Windows Sockets實現(xiàn)的細節(jié)。應用程序或DLL只能在一次成功的WSAStartu

37、p()調用之后,才能進一步調用其它的Winsock API函數(shù)。7.4Winsock中建立連接的函數(shù)及其應用7.4.1 加載協(xié)議棧(WSAStartup)1.函數(shù)格式int WSAStartup(WORD wVersionRequested,LPWSADATA lpWSAData);2.函數(shù)參數(shù)說明WSAStartup函數(shù)有兩個參數(shù),其含義是:7.4Winsock中建立連接的函數(shù)及其應用7.4.1 加載協(xié)議棧(WSAStartup)wVersionRequested:第一個參數(shù)是一個WORD型(雙字節(jié)型)數(shù)值,它指定準備在應用程序中要使用的Winsock庫的版本號。其中用高位字節(jié)指定副版本,而

38、低位字節(jié)則指定主版本。就目前的常用的Win32平臺而言,Winsock 2庫的版本是2.2(在早期的Windows 95等版本中為Winsock 1.1)。如果需要加載Winsock 2.2版,則應指定這個值為(0 x0202),也可使用宏MAKEWORD(X,Y),其中X為高位字節(jié),Y為低位字節(jié),如MAKEWORD(2,2)。LpWSAData:第二個參數(shù)是一個指向WSADATA結構的指針。當該函數(shù)被調用時,它返回關于Windows Sockets實現(xiàn)的詳細信息,該結構的定義如下:7.4Winsock中建立連接的函數(shù)及其應用7.4.1 加載協(xié)議棧(WSAStartup)typedef str

39、uct WSADataWORD wVersion;WORD wHighVersion;Char szDescriptionWSADESCRIPTION_LEN+1;Char szSystemStatusWSASYS_STATUS_LEN+1;unsigned short iMaxSockets;unsigned short iMaxUdpDg;char FAR * lpVendorInfo; WSADATA,F(xiàn)AR *LPWSADATA;7.4Winsock中建立連接的函數(shù)及其應用7.4.1 加載協(xié)議棧(WSAStartup)該結構各字段的含義說明如下:wVersion:調用者希望使用的Win

40、sock版本號。wHighVersion:加載的Winsock庫所支持的最高Winsock版本號,通常和第1個分量wVersion的值相同。szDescription:系統(tǒng)加載的Winsock庫的說明字符串,如“Winsock 2.0”。szSystemStatus:系統(tǒng)狀態(tài)或配置信息的說明字符串。iMaxSockets:套接口的最大編號(該字段被Winsock 2或其后的版本所忽略)。iMaxUdpDg:UDP數(shù)據(jù)報的最大容量(該字段被Winsock 2或其后的版本所忽略)。7.4Winsock中建立連接的函數(shù)及其應用7.4.1 加載協(xié)議棧(WSAStartup)lpVendorInfo:廠

41、商專有信息(該字段被Winsock 2或其后的版本所忽略)。該結構中,WSAStartup()函數(shù)返回的比較有用的信息是wVersion和wHighVersion,這是兩個關于Winsock版本號的字段,其它字段則很少使用。其中最后3個字段在Winsock 2中只是為了保持與低版本的Winsock兼容性而保留的字段,實際已經(jīng)不使用這3個字段了。3.函數(shù)返回信息WSAStartup()函數(shù)的返回值是一個整數(shù),如果調用成功則返回0。WSAStartup()函數(shù)調用不成功時返回如下的錯誤信息:WSASYSNOTREADY:在Winsock的頭文件Winsock 2.h中,該錯誤代碼定義的數(shù)值為100

42、91,它表明加載的Winsock DLL不存在或底層的網(wǎng)絡子系統(tǒng)無法使用。7.4Winsock中建立連接的函數(shù)及其應用7.4.1 加載協(xié)議棧(WSAStartup)WSAVERNOTSUPPORTED:該代碼的數(shù)值為10092,所需的Windows Sockets API的版本未由特定的Windows Sockets實現(xiàn)提供。如果由wVersion返回的版本用戶不能接受,則要調用WSACleanup()函數(shù)清除對Winsock的加載。WSAEINVAL:該代碼的數(shù)值為10022,說明應用程序指出的Windows Sockets版本不能被該Winsock DLL的實現(xiàn)所支持。WSAEINPROG

43、RESS:該代碼的數(shù)值為10036,說明一個阻塞的Winsock調用正在進行中。WSAEPROCLIM:該代碼的數(shù)值為10067,說明已經(jīng)達到了Windows Sockets實現(xiàn)所支持的任務數(shù)量的極限。WSAEFAULT:該代碼數(shù)值為10014,說明lpWSAData參數(shù)是一個無效的指針。7.4Winsock中建立連接的函數(shù)及其應用7.4.2創(chuàng)建套接口(socket或WSASocket)應用程序在使用套接口通信之前,必須要擁有一個套接口。在Winsock中,要使用Socket()或WSASocket()函數(shù)來給一個網(wǎng)絡應用程序創(chuàng)建一個套接口。函數(shù)格式在Winsock 1中提供的格式是:SOCK

44、ET socket(int af,int type,int protocol);7.4Winsock中建立連接的函數(shù)及其應用7.4.2創(chuàng)建套接口(socket或WSASocket)在Winsock 2中提供的擴展格式是:SOCKET WSASocket(int af,int type,int protocol,LPWSAPROTOCOL_INFO lpProtocolInfo,Group g,int iFlags);7.4Winsock中建立連接的函數(shù)及其應用7.4.3地址綁定(bind)當用socket()創(chuàng)建了一個套接口后,該套接口還是不能直接使用的,因為它只存在于一個名字空間(地址族)中

45、,也就是說它只確定了通信所希望使用的服務類型,并沒有與該主機上提供服務的某端口聯(lián)系在一起,這樣的套接口可以叫未命名的套接口。bind()函數(shù)通過給一個未命名的套接口分配一個本地名字,來為套接口建立本地綁定(即把一個套接口與一個主機地址和端口號聯(lián)系起來)。本函數(shù)適用于數(shù)據(jù)報或流類套接口。函數(shù)格式int bind(SOCKET s,const struct sockaddr FAR* name,int namelen);7.4Winsock中建立連接的函數(shù)及其應用7.4.4服務器端監(jiān)聽連接(listen)當在一個服務器端程序中,用socket()函數(shù)成功創(chuàng)建了一個套接口,并用bind()函數(shù)和一個

46、指定的地址關聯(lián)(即綁定)在一起后,就要指示該套接口進入監(jiān)聽連接請求的狀態(tài),可以接收由客戶端發(fā)出的連接請求,這時就要用Winsock API函數(shù)listen()。函數(shù)格式int listen(SOCKET s,int backlog);7.4Winsock中建立連接的函數(shù)及其應用7.4.5客戶端請求連接(connect或WSAConnect)當服務器端建立好套接口并與一個本地地址綁定后,就進入監(jiān)聽狀態(tài),等待客戶發(fā)出連接請求,從而為客戶提供服務。在客戶端當套接口建立好之后,就要調用connect()函數(shù),提出與一個服務器建立連接的請求,如果服務器接受請求,就可以在服務器的遠程套接口與客戶端的本地套接口之間建立一條連接。函數(shù)格式在Winsock 1中提供的格式是:int connect(SOCKET s,const struct sockaddr FAR* name,int namelen);7.4Winsock中建立連接的函數(shù)及其應用7.4.6服務器端接受連接(accept或WSAAccept)在服務器端通過listen()函數(shù)調用表示服務器進入監(jiān)聽客戶的連接請求狀態(tài),而在服務器端調用accept()函數(shù)表示可以接收來自客戶端由connect()發(fā)出的

溫馨提示

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

評論

0/150

提交評論