基于TCPIP協(xié)議的網(wǎng)絡(luò)編程-新_第1頁(yè)
基于TCPIP協(xié)議的網(wǎng)絡(luò)編程-新_第2頁(yè)
基于TCPIP協(xié)議的網(wǎng)絡(luò)編程-新_第3頁(yè)
基于TCPIP協(xié)議的網(wǎng)絡(luò)編程-新_第4頁(yè)
基于TCPIP協(xié)議的網(wǎng)絡(luò)編程-新_第5頁(yè)
已閱讀5頁(yè),還剩100頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

網(wǎng)絡(luò)編程與開發(fā)技術(shù)

天津職業(yè)技術(shù)師范大學(xué)信息學(xué)院第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程內(nèi)容提要1、TCP/IP概述2、協(xié)議簡(jiǎn)介3、地址與名字解析4、網(wǎng)間進(jìn)程通信及端口號(hào)5、Winsock基本概念6、常用Winsock函數(shù)7、會(huì)話通信程序設(shè)計(jì)8、數(shù)據(jù)報(bào)通信程序設(shè)計(jì)9、Winsock多播與廣播通信程序設(shè)計(jì)10、WinsockI/O模型§3.1TCP/IP概述第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程1、TCP/IP協(xié)議簇

TCP/IP協(xié)議簇與ISO/OSI模型的對(duì)應(yīng)關(guān)系如圖:線纜RARPARP網(wǎng)絡(luò)接口UpperProtocolTCPUDPProgramIPICMPIGMP物理層數(shù)據(jù)鏈路層網(wǎng)絡(luò)層傳輸層應(yīng)用層物理層鏈路層網(wǎng)絡(luò)層應(yīng)用層1236547OSI/RM表示層會(huì)話層傳輸層TCP/IP協(xié)議層§3.1TCP/IP概述

網(wǎng)絡(luò)中兩節(jié)點(diǎn)間的數(shù)據(jù)傳送先從發(fā)送節(jié)點(diǎn)的高層向底層發(fā)送,每向下傳送一層,根據(jù)本層的協(xié)議添加本層的報(bào)頭,達(dá)到物理層以后,再水平傳送到接收節(jié)點(diǎn)的物理層,再接收節(jié)點(diǎn)的物理層垂直向上發(fā)送,向上傳送一層則去掉一個(gè)報(bào)頭。一個(gè)節(jié)點(diǎn)的各層只能實(shí)現(xiàn)與上下相鄰層間的通信,相鄰層之間也僅僅是相互通信,對(duì)其內(nèi)部的工作過(guò)程是不必知道的。除物理層為水平通信外,其它各層都是垂直通信。也就是說(shuō),網(wǎng)絡(luò)中各節(jié)點(diǎn)之間的直接接口只能是物理層。節(jié)點(diǎn)的各層都有自己的協(xié)議,而且這些協(xié)議都是相互獨(dú)立的,各層的功能任務(wù)也是十分明確的。每一層利用相鄰的下一層提供的服務(wù)完成一組特定的功能,每一層功能實(shí)現(xiàn)的服務(wù)僅僅提供給相鄰的上一層。

第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.1TCP/IP概述每一層負(fù)責(zé)的功能如下:鏈路層:也稱數(shù)據(jù)鏈路層或網(wǎng)絡(luò)接口層,通常包括設(shè)備驅(qū)動(dòng)程序和網(wǎng)絡(luò)接口卡,它們一起處理與電纜(或其他任何傳輸媒介)的物理接口細(xì)節(jié)。該層包括的協(xié)議有:ARP和RARP。網(wǎng)絡(luò)層:負(fù)責(zé)分組在網(wǎng)絡(luò)中的活動(dòng),包括IP協(xié)議、ICMP以及IGMP協(xié)議(Internet組管理協(xié)議)。傳輸層:該層主要為兩臺(tái)主機(jī)上的應(yīng)用程序提供端到端的數(shù)據(jù)通信,它分為兩個(gè)不同的協(xié)議:TCP和UDP(用戶數(shù)據(jù)報(bào)協(xié)議)。TCP協(xié)議提供端到端的質(zhì)量保證的數(shù)據(jù)傳輸,該層負(fù)責(zé)數(shù)據(jù)的分組、質(zhì)量控制和超時(shí)重發(fā)等。UDP協(xié)議則只提供簡(jiǎn)單的把數(shù)據(jù)報(bào)從一端發(fā)送到另一端,至于數(shù)據(jù)是否到達(dá)或按時(shí)到達(dá)、數(shù)據(jù)是否損壞都必須由應(yīng)用層來(lái)做。應(yīng)用層:該層負(fù)責(zé)處理實(shí)際的應(yīng)用程序細(xì)節(jié),包括Telnet(電子公告板)、HTTP(WorldWideWeb服務(wù))、SMTP(簡(jiǎn)單郵件傳輸協(xié)議)、FTP(簡(jiǎn)單文件傳輸協(xié)議)和SNMP(簡(jiǎn)單網(wǎng)絡(luò)管理協(xié)議)等著名協(xié)議。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.1TCP/IP概述2、Winsock概述

Winsock是從Unix系統(tǒng)的Socket接口演變而來(lái)的。在20世紀(jì)90年代初,網(wǎng)絡(luò)軟件開發(fā)商決定為Windows開發(fā)一套通用TCP/IP編程接口,類似于Unix下的Socket,到1994年,它被正式稱為Winsock,這一接口迅速被所有的軟件商所接受,通過(guò)C語(yǔ)言動(dòng)態(tài)鏈接庫(kù)方式提供給用戶及軟件開發(fā)者。

Winsock繼承了BerkeleySockets的主要特征,同時(shí)進(jìn)行了重要擴(kuò)充。主要是提供了一些異步函數(shù),并增加了符合Windows消息驅(qū)動(dòng)機(jī)制的網(wǎng)絡(luò)事件異步選擇方式。這些擴(kuò)充有利于程序員編寫符合Windows編程模式的軟件。

Winsock接口包含了一組網(wǎng)絡(luò)I/O和獲取網(wǎng)絡(luò)信息的庫(kù)函數(shù),網(wǎng)絡(luò)應(yīng)用程序通過(guò)調(diào)用這部分函數(shù)實(shí)現(xiàn)自己的功能。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.2協(xié)議簡(jiǎn)介IP協(xié)議傳輸層協(xié)議客戶機(jī)/服務(wù)器模式第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.2.1IP協(xié)議IP層提供無(wú)連接的數(shù)據(jù)報(bào)傳輸機(jī)制。所以IP協(xié)議比較簡(jiǎn)單,不保證傳輸?shù)目煽啃?。IP協(xié)議解決的最大的一個(gè)問(wèn)題是路由選擇問(wèn)題。

TCP/IP技術(shù)是為包容物理網(wǎng)絡(luò)技術(shù)的多樣性而設(shè)計(jì)的,而這種包容性主要體現(xiàn)在IP層當(dāng)中。各種網(wǎng)絡(luò)技術(shù)的幀格式、地址格式等上層協(xié)議差別很大,TCP/IP的重要思想之一就是提供一致的IP數(shù)據(jù)報(bào)格式。在TCP/IP協(xié)議簇中,所有上層協(xié)議都必須通過(guò)IP層傳輸外出數(shù)據(jù)報(bào),而所有下層協(xié)議接收到的信息首先必須交給IP層處理(判斷是接受還是拋棄)。IP協(xié)議的這一特點(diǎn)充分體現(xiàn)了它在TCP/IP分層結(jié)構(gòu)中的重要作用,作為通用的數(shù)據(jù)報(bào)傳輸手段,IP協(xié)議可以說(shuō)是TCP/IP協(xié)議簇的核心。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.2.1IP協(xié)議第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程版本號(hào)首部長(zhǎng)度服務(wù)類型總長(zhǎng)度標(biāo)識(shí)標(biāo)志分片偏移量壽命協(xié)議首部校驗(yàn)和源站IP地址目的站IP地址IP選項(xiàng)填充數(shù)據(jù)……IP包頭結(jié)構(gòu)服務(wù)類型:優(yōu)先級(jí)(3)D延遲T通信量R可靠性C成本0標(biāo)志:0DFMF§3.2.1IP協(xié)議TCP包由頭和數(shù)據(jù)區(qū)組成。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程源端口號(hào)目的端口號(hào)序號(hào)確認(rèn)號(hào)頭長(zhǎng)度標(biāo)志保留窗口大小TCP校驗(yàn)和緊急指針任選(如果有)填充數(shù)據(jù)……TCP頭結(jié)構(gòu)§3.2.2傳輸層協(xié)議

TCP/IP協(xié)議簇中在傳輸層有兩個(gè)重要的協(xié)議:TCP和UDP,前者提供高可靠性服務(wù),后者提供高效率服務(wù)。對(duì)二者的選擇取決于應(yīng)用環(huán)境和需求。(1)TCP協(xié)議

TCP協(xié)議可靠性很高,幾乎可以解決所有的傳輸可靠性問(wèn)題。面向連接的TCP對(duì)可靠性的保證首先是它在進(jìn)行實(shí)際數(shù)據(jù)傳輸前,必須在信源端和信宿端建立一條連接。假如由于種種原因,連接建立不成功,則信源端不會(huì)像UDP一樣貿(mào)然向信宿端發(fā)送數(shù)據(jù)。其次,面向連接傳輸?shù)拿恳粋€(gè)報(bào)文都需接收端確認(rèn),未確認(rèn)報(bào)文被認(rèn)為是出錯(cuò)報(bào)文。TCP協(xié)議建立在不可靠的IP協(xié)議之上的,IP不能提供任何可靠性機(jī)制,所以TCP的可靠性完全由自己實(shí)現(xiàn)。

TCP采用的最基本的可靠性技術(shù)是:確認(rèn)與重傳。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.2.2傳輸層協(xié)議(2)UDP協(xié)議

用戶數(shù)據(jù)報(bào)協(xié)議UDP(UserDatagramProtocol)建立在IP協(xié)議之上,同IP協(xié)議一樣提供無(wú)連接數(shù)據(jù)報(bào)傳輸。相對(duì)于IP協(xié)議,它唯一增加的能力是提供協(xié)議端口,以保證進(jìn)程通信。

UDP的是不可靠的,因此,基于UDP的應(yīng)用程序在不可靠子網(wǎng)上必須自己解決可靠性(報(bào)文丟失、重復(fù)、失序和流控等)問(wèn)題。

第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.2.3客戶機(jī)/服務(wù)器模式

很多數(shù)據(jù)處理系統(tǒng)都采用開放系統(tǒng)結(jié)構(gòu)的客戶機(jī)/服務(wù)器(Clinet/Server)網(wǎng)絡(luò)模型。服務(wù)器是一個(gè)進(jìn)程,它一直等待著客戶進(jìn)程的請(qǐng)求以便為客戶進(jìn)程服務(wù),客戶進(jìn)程向服務(wù)器提出請(qǐng)求,服務(wù)器對(duì)請(qǐng)求做相應(yīng)的處理并執(zhí)行被請(qǐng)求的任務(wù),然后將結(jié)果返回給客戶機(jī)。典型的情況如下:

a.服務(wù)器進(jìn)程開始執(zhí)行,首先初始化本身,然后進(jìn)入睡眠狀態(tài)以等待客戶進(jìn)程的請(qǐng)求。通常是在一個(gè)眾所周知的地址監(jiān)聽客戶對(duì)服務(wù)的請(qǐng)求。

b.在本系統(tǒng)或與服務(wù)器相連的其它系統(tǒng)上,某一客戶進(jìn)程開始執(zhí)行,把請(qǐng)求發(fā)送給服務(wù)器進(jìn)程要求服務(wù)。

c.服務(wù)器進(jìn)程“驚醒”并且為客戶提供服務(wù),作出適當(dāng)?shù)姆磻?yīng)。

第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.3地址與名字解析IP地址地址解析域名解析第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.3.1IP地址IPv4

在TCP協(xié)議棧中,編址由IP協(xié)議規(guī)定,IP標(biāo)準(zhǔn)分配給每臺(tái)主機(jī)一個(gè)32位的二進(jìn)制數(shù)作為該主機(jī)的IP地址。IPv6

在新出臺(tái)的IPv6中IP地址升至128位,這樣IP地址資源就變得更加豐富,但離實(shí)用化還有一段距離。IPv4地址格式:

32位IP地址被分割為兩部分:前綴和后綴。前綴用于確定計(jì)算機(jī)從所屬的物理網(wǎng)絡(luò),稱為網(wǎng)絡(luò)標(biāo)識(shí),后綴則用于確定網(wǎng)絡(luò)上一臺(tái)單獨(dú)的計(jì)算機(jī),稱為主機(jī)標(biāo)識(shí)。互連網(wǎng)中每一個(gè)物理網(wǎng)絡(luò)都有一個(gè)唯一的值作為網(wǎng)絡(luò)標(biāo)識(shí)。IP地址的層次性保證了以下兩個(gè)重要性質(zhì):每臺(tái)計(jì)算機(jī)分配一個(gè)唯一的地址。雖然網(wǎng)絡(luò)號(hào)分配必須全球一致,但主機(jī)標(biāo)識(shí)可本地分配,不須全球一致。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.3.1IP地址

IP地址分為五類:A類、B類、C類、D類和E類。其中A類、B類和C類為基本類,D類多用于多播傳送,E類屬于保留類,現(xiàn)在不用。它們的格式如下(其中,*代表網(wǎng)絡(luò)標(biāo)識(shí)位數(shù)):A類:0*******xxxxxxxxxxxxxxxxxxxxxxxxB類:10**************xxxxxxxxxxxxxxxxC類:110*********************xxxxxxxxD類:1110xxxxxxxxxxxxxxxxxxxxxxxxxxxxE類:1111xxxxxxxxxxxxxxxxxxxxxxxxxxxxIP地址一般采用點(diǎn)分十進(jìn)制的表示方法,例如:100000001001101000000011000000000——>第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程類型范圍A類

——55B類——55C類——55D類——55E類——55§3.3.1IP地址幾個(gè)特殊的IP地址:網(wǎng)絡(luò)地址:IP中主機(jī)地址為0的地址表示網(wǎng)絡(luò)地址。如廣播地址:網(wǎng)絡(luò)標(biāo)識(shí)后的所有位都是1的后綴,就是直接廣播地址。如55回送地址:用于測(cè)試。子網(wǎng):

子網(wǎng)的劃分是通過(guò)子網(wǎng)掩碼來(lái)確定的。子網(wǎng)掩碼是一個(gè)32bit的值,其中值為1的比特留給網(wǎng)絡(luò)號(hào)和子網(wǎng)號(hào),為0的比特留給主機(jī)號(hào)。 網(wǎng)絡(luò)/子網(wǎng)地址=主機(jī)IP地址&&子網(wǎng)掩碼

第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.3.2地址解析

地址解析用來(lái)實(shí)現(xiàn)IP地址向物理地址(MAC地址)的轉(zhuǎn)換。物理地址:在任何一個(gè)物理網(wǎng)絡(luò)中,各站點(diǎn)都有一個(gè)機(jī)器可識(shí)別的地址,該地址叫物理地址。該物理地址被分配給每一塊網(wǎng)絡(luò)適配卡,它是一個(gè)48位的二進(jìn)制數(shù),它唯一地標(biāo)識(shí)網(wǎng)絡(luò)中的主機(jī)。

IP地址:是一個(gè)32位的二進(jìn)制數(shù),通常由網(wǎng)絡(luò)管理員分配給網(wǎng)絡(luò)中的設(shè)備。

ARP(AddressResolutionProtocol):地址解析協(xié)議,完成從IP地址到物理地址的映射。

RARP(ReverseAddressResolutionProtocol):反向地址解析,完成從物理地址到IP地址的映射。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.3.3域名解析

在TCP/IP協(xié)議簇中,域名系統(tǒng)(DNS)用來(lái)完成主機(jī)名(及電子郵件地址)到IP地址之間的映射。

DNS的核心是分級(jí)的、基于域的命名機(jī)制和為了實(shí)現(xiàn)這個(gè)命名機(jī)制的分布式數(shù)據(jù)庫(kù)系統(tǒng)。DNS是典型的客戶/服務(wù)器模式,安裝了DNS,提供域名解析功能的計(jì)算機(jī)就是域名服務(wù)器。因特網(wǎng)域名結(jié)構(gòu)是按照層次結(jié)構(gòu)組織的。首先把整個(gè)因特網(wǎng)劃分為多個(gè)域,我們稱為頂級(jí)域,并為每個(gè)頂級(jí)域規(guī)定了國(guó)際通用的域名。頂級(jí)域名的劃分采用了兩種劃分模式:組織模式和地理模式。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程頂級(jí)域名分配情況Com商業(yè)組織Edu教育機(jī)構(gòu)Gov政府部門Mil軍事部門Net主要網(wǎng)絡(luò)支持中心Org上述以外的組織Int國(guó)際組織國(guó)家代碼各個(gè)國(guó)家§3.4網(wǎng)間進(jìn)程通信及端口號(hào)端口:

TCP或UDP用標(biāo)識(shí)通信主機(jī)中不同通信進(jìn)程的編號(hào),簡(jiǎn)稱端口。工作原理:各個(gè)通信進(jìn)程通過(guò)系統(tǒng)調(diào)用與某些端口建立綁定,傳輸層傳送到該端口的所有數(shù)據(jù)相應(yīng)地被與其綁定的進(jìn)程接收。端口號(hào)格式:TCP和UDP采用16bit的端口號(hào)來(lái)識(shí)別進(jìn)程。由于TCP和UDP是完全獨(dú)立的兩個(gè)軟件模塊,因此各自的端口號(hào)也相互獨(dú)立。例如,TCP有一個(gè)1001號(hào)端口,同樣UDP也可以有一個(gè)1001號(hào)端口,它們并不沖突。端口與協(xié)議在進(jìn)程通信中是密不可分的,不同協(xié)議的端口之間沒(méi)有任何的聯(lián)系。對(duì)TCP和UDP而言,可以提供65535(216)個(gè)端口,如何為進(jìn)程分配端口是一個(gè)重要的問(wèn)題。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.5Winsock基本概念(1)套接字一個(gè)套接字是通信的一個(gè)端點(diǎn),一個(gè)正在被使用的套接字都有它的類型和與其相關(guān)的進(jìn)程。套接字根據(jù)通信性質(zhì)分為兩類:會(huì)話套接字和數(shù)據(jù)報(bào)套接字。會(huì)話套接字提供一種可靠的面向連接的數(shù)據(jù)傳輸方法,通常會(huì)話套接字使用TCP協(xié)議。通信雙方進(jìn)行數(shù)據(jù)交換前,必須建立一條連接。數(shù)據(jù)報(bào)套接字支持雙向通信,提供不可靠的、非連接的報(bào)通信方式。數(shù)據(jù)報(bào)套接字通常使用UDP協(xié)議,具有向多個(gè)目標(biāo)地址發(fā)送廣播數(shù)據(jù)報(bào)的能力。數(shù)據(jù)報(bào)并不十分可靠,需要應(yīng)用程序負(fù)責(zé)管理數(shù)據(jù)報(bào)的排序和可靠性。(2)帶外數(shù)據(jù)也稱為TCP緊急數(shù)據(jù)。帶外數(shù)據(jù)是獨(dú)立于普通數(shù)據(jù)傳送給用戶的,對(duì)于僅支持帶內(nèi)數(shù)據(jù)的通信協(xié)議來(lái)說(shuō)(例如緊急數(shù)據(jù)是與普通數(shù)據(jù)在同一序列中發(fā)送),系統(tǒng)通常把緊急數(shù)據(jù)從普通數(shù)據(jù)中分離出來(lái)單獨(dú)存放。這就允許用戶在順序接收緊急數(shù)據(jù)和非順序接收緊急數(shù)據(jù)之間作出選擇。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.5Winsock基本概念(3)廣播數(shù)據(jù)報(bào)套接字可以用來(lái)向許多系統(tǒng)支持的網(wǎng)絡(luò)發(fā)送廣播數(shù)據(jù)包。要實(shí)現(xiàn)這種功能,網(wǎng)絡(luò)本身必須支持廣播功能。廣播信息將會(huì)給網(wǎng)絡(luò)造成極重的負(fù)擔(dān),因?yàn)樗鼈円缶W(wǎng)絡(luò)上的每臺(tái)主機(jī)都為它們服務(wù),所以發(fā)送廣播數(shù)據(jù)包的能力被限制于那些用顯式標(biāo)記了允許廣播的套接字中。廣播通常應(yīng)用于兩種情況:一種是應(yīng)用程序希望在本地網(wǎng)絡(luò)中找到一個(gè)資源,而應(yīng)用程序?qū)υ撡Y源的地址有沒(méi)有任何先驗(yàn)知識(shí)。而另一種是一些重要的功能,例如路由要求把它們的信息發(fā)送給所有可以找到的鄰機(jī)。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.5Winsock基本概念(4)字節(jié)順序

不同的計(jì)算機(jī)使用不同的字節(jié)順序存儲(chǔ)數(shù)據(jù)。Intel處理器使用的字節(jié)順序稱為“Little-Endian”,而Internet網(wǎng)絡(luò)的字節(jié)順序稱為“Big-Endian”,即主機(jī)序和網(wǎng)絡(luò)序它們的字節(jié)順序是相反的。例如:

1234H的主機(jī)序:3412H1234H的網(wǎng)絡(luò)序:1234H

任何Winsock函數(shù)對(duì)IP地址和端口號(hào)的使用均是按照網(wǎng)絡(luò)字節(jié)順序組織的。在很多情況下,用戶要在主機(jī)字節(jié)順序和網(wǎng)絡(luò)字節(jié)順序之間進(jìn)行轉(zhuǎn)換,程序員應(yīng)該使用WinsockAPI中標(biāo)準(zhǔn)的轉(zhuǎn)換函數(shù),而不要自己編寫轉(zhuǎn)換代碼。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.5Winsock基本概念(5)原始套接字

原始套接字是用SOCK_RAW打開的套接字,利用原始套接字(RawSocket)可訪問(wèn)位于基層的傳輸協(xié)議(例如IP協(xié)議、ICMP協(xié)議、IGMP協(xié)議等),而不象其它套接字類型只能訪問(wèn)傳輸層TCP和UDP協(xié)議。要想使用原始套接字,要求對(duì)基層的協(xié)議結(jié)構(gòu)有一定程度的認(rèn)識(shí)。(6)阻塞和非阻塞

套接字可以處于阻塞模式或非阻塞模式。在阻塞模式下,I/O操作完成前,執(zhí)行操作的Winsock函數(shù)會(huì)一直等待下去,不會(huì)立即返回(將控制權(quán)交還給程序),這就意味著任一個(gè)線程在某一時(shí)刻只能執(zhí)行一個(gè)I/O操作,而且應(yīng)用程序很難同時(shí)通過(guò)多個(gè)建好連接的套接字進(jìn)行通信。而非阻塞模式下沒(méi)有這樣的要求,Winsock函數(shù)無(wú)論如何都會(huì)返回并交出程序的控制權(quán)。在默認(rèn)的情況下,套接字是阻塞模式。

第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.5Winsock基本概念(3)錯(cuò)誤檢查與控制

對(duì)編寫成功的Winsock應(yīng)用程序而言,錯(cuò)誤檢查和控制是至關(guān)重要的。對(duì)于Winsock函數(shù)而言,返回錯(cuò)誤是非常常見的。但是多數(shù)情況下,這些錯(cuò)誤是無(wú)關(guān)緊要的,通信仍可在套接字上進(jìn)行。返回的錯(cuò)誤值可以有多種,但最常見的錯(cuò)誤是SOCK_ERROR。SOCK_ERROR的值是-1。調(diào)用一個(gè)Winsock函數(shù),如果發(fā)生錯(cuò)誤,就可用WSAGetLastError函數(shù)來(lái)獲得一段代碼,這段代碼明確地表明產(chǎn)生錯(cuò)誤的原因。該函數(shù)的定義為:intWSAGetLastError(void);

發(fā)生錯(cuò)誤后調(diào)用這個(gè)函數(shù),就會(huì)返回所發(fā)生的特定錯(cuò)誤的完整代碼。這些錯(cuò)誤都是已經(jīng)預(yù)定義的常量值。

第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.6常用Winsock函數(shù)Winsock初始化函數(shù)基本W(wǎng)insock函數(shù)數(shù)據(jù)傳輸函數(shù)字節(jié)順序及地址轉(zhuǎn)換函數(shù)網(wǎng)絡(luò)信息查詢函數(shù)第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.6.1Winsock初始化函數(shù)(1)WSAStartup()功能:加載WinsockDLL的相應(yīng)版本。格式:

intWSAStartup(WORDwVersionRequested,LPWSADATAlpWSAData);參數(shù)說(shuō)明:

wVersionRequested:用于指定準(zhǔn)備加載的Winsock版本,高位字節(jié)指定所需要的Winsock庫(kù)的副版本,而低位字節(jié)則是主版本。可用宏MAKEWORD(X,Y)來(lái)獲得wVersionRequested的正確值(X是高位字節(jié),Y是低位字節(jié))。lpWSAData:指向LPWSADATA結(jié)構(gòu)的指針,WSAStartup用其加載的庫(kù)版本有關(guān)的信息。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.6.1Winsock初始化函數(shù)typedefstructWSAData{WORDwVersion;WORDwHighVersion;charszDescription[WSADESCRIPTION_LEN+1];charszSystemStatus[WSASYS_STATUS_LEN+1];unsignedshortiMaxSockets;unsignedshortiMaxUdpDg;charFAR*lpVendorInfo;}WSADATA,FAR*LPWSADATA;第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程(2)WSACleanup()功能:終止對(duì)WinsockDLL的使用,并釋放資源。格式:intWSACleanup(void);

注釋:該函數(shù)不帶任何參數(shù),若調(diào)用成功則返回0,否則返回錯(cuò)誤。

§3.6.2基本W(wǎng)insock函數(shù)

Winsock基本函數(shù)包括socket、bind、connect、listen、accept、closesocket、shutdown等。(1)socket()

功能:創(chuàng)建一個(gè)套接字。格式:SOCKETsocket(intaf,inttype,intprotocol);參數(shù)說(shuō)明:af:指定網(wǎng)絡(luò)地址類型,一般取AF_INET,表示該套接字在Internet域中進(jìn)行通信。type:用于指定套接字類型,套接字類型可以取五個(gè)值:SOCK_STREAM(會(huì)話套接字)、SOCK_DGRAM(數(shù)據(jù)報(bào)套接字)、SOCK_SEQPACKET、SOCK_RAW(原始套接字)和SOCK_RDM。protocol:指定網(wǎng)絡(luò)協(xié)議,一般取0,表示默認(rèn)為TCP/IP協(xié)議。

WinsockAPI是建立在套接字基礎(chǔ)上的。套接字從實(shí)質(zhì)上講,就是一個(gè)指向傳輸提供者的句柄。Win32中套接字不同于其他文件描述符,它是一個(gè)獨(dú)立的類型——SOCKET。

第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.6.2基本W(wǎng)insock函數(shù)(2)bind()功能:將一本地地址與一套接字綁定。格式:intbind(SOCKETs,conststructsockaddr*name,intnamelen);參數(shù)說(shuō)明:s:標(biāo)識(shí)一未捆綁套接口的句柄。即等待和客戶端連接的套接字。name:賦予套接字的地址。它是用structsockaddr結(jié)構(gòu)定義的,sockaddr結(jié)構(gòu)定義如下:

structsockaddr{u_shortsa_family;charsa_data[14];};

一般情況下另一個(gè)與該地址結(jié)構(gòu)大小相同的sockaddr_in結(jié)構(gòu)更為常用,sockaddr_in結(jié)構(gòu)用來(lái)標(biāo)識(shí)TCP/IP協(xié)議下的地址。

第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.6.2基本W(wǎng)insock函數(shù)Sockaddr_in的結(jié)構(gòu)定義如下:

structsockaddr_in{shortsin_family;u_shortsin_port;structin_addrsin_addr;charsin_zero[8];}

sin_family:必須設(shè)為AF_INET,表示該socket處于Internet域。sin_port:用于指定服務(wù)端口,在選擇服務(wù)端口時(shí)必須特別小心,因?yàn)橛行┛捎枚丝谝褳楣潭ǖ姆?wù)保留。如果把端口號(hào)設(shè)為0,則Winsock將為應(yīng)用程序分配一個(gè)在1024——5000之間的端口值。sin_addr:用于把一個(gè)IP地址保存為一個(gè)4字節(jié)的數(shù),它是無(wú)符號(hào)整數(shù)類型。函數(shù)inet_addr可以把點(diǎn)分式IP地址轉(zhuǎn)換為一個(gè)32位的無(wú)符號(hào)長(zhǎng)整數(shù)。inet_addr定義如下:unsignedlonginet_addr(constcharFAR*cp);cp:是一個(gè)空中止符字符串,它認(rèn)可點(diǎn)分式表示的IP地址。這個(gè)函數(shù)的返回是一個(gè)網(wǎng)絡(luò)字節(jié)順序的32位長(zhǎng)整數(shù)。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.6.2基本W(wǎng)insock函數(shù)sin_zero:只充當(dāng)填充項(xiàng)的作用,以使sockaddr_in結(jié)構(gòu)和sockaddr結(jié)構(gòu)的長(zhǎng)度一樣。namelen:代表name名字的長(zhǎng)度。也就是要傳遞的、由協(xié)議決定的地址的長(zhǎng)度。

bind將指定的套接字同一個(gè)已知地址綁定在一起。一旦出錯(cuò),bind函數(shù)會(huì)返回SOCKET_ERROR。對(duì)bind來(lái)說(shuō),最常見的錯(cuò)誤是WSAEADDRINUSE。如果使用TCP/IP,那么該錯(cuò)誤表示另一個(gè)進(jìn)程已經(jīng)同本地的IP接口綁定到了一起,或者那個(gè)IP地址和端口號(hào)處于TIME_WAIT狀態(tài)。假如對(duì)一個(gè)已綁定套接字調(diào)用bind,便會(huì)返回WSAEFFAULT錯(cuò)誤。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.6.2基本W(wǎng)insock函數(shù)下面舉例說(shuō)明如何

在一個(gè)TCP連接上進(jìn)行套接字綁定:SOCKETs;Structsockaddr_intcpaddr;intport=5150;intnSockErr;s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);tcpaddr.sin_family=AF_INET;tcpaddr_sin_port=htons(port);tcpaddr.sin_addr.s_addr=htonl(INADDR_ANY);//調(diào)用bind函數(shù)分配地址

if(bind(s,(SOCKADDR*)&tcpaddr,sizeof(tcpaddr))==SOCKET_ERROR) nSockErr=WSAGetLastError();//處理錯(cuò)誤在這個(gè)例子中,先創(chuàng)建了一個(gè)套接字,然后設(shè)置了TCP/IP的地址,最后把套接字綁定到默認(rèn)IP地址的5150端口上。這里的IP地址為INADDR_ANY,以允許服務(wù)進(jìn)程監(jiān)聽主機(jī)上面每個(gè)網(wǎng)絡(luò)接口上的客戶機(jī)活動(dòng)。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.6.2基本W(wǎng)insock函數(shù)(3)listen()功能:將套接字置為監(jiān)聽模式,等待客戶端提出的連接申請(qǐng)。格式:

intPASCALFARlisten(SOCKETs,intbacklog);

參數(shù)說(shuō)明:

s:用于標(biāo)識(shí)一個(gè)已捆綁未連接套接字的句柄。

backlog:表示等待連接隊(duì)列的最大長(zhǎng)度。如果無(wú)錯(cuò)誤發(fā)生,listen返回0,否則返回SOCKET_ERROR錯(cuò)誤,最常見的錯(cuò)誤是WSAEINVAL,該錯(cuò)誤通常表示listen之前沒(méi)有調(diào)用bind。應(yīng)用程序可通過(guò)WSAGetLastError()獲取相應(yīng)錯(cuò)誤代碼。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.6.2基本W(wǎng)insock函數(shù)(4)accept()

功能:在指定套接字上接受一個(gè)連接,返回一個(gè)新的套接字描述字。

格式:SOCKETPASCALFARaccept(SOCKETs,structsockaddrFAR*addr,intFAR*addrlen);

參數(shù):

s:套接字句柄,該套接字在listen()后已經(jīng)監(jiān)聽連接。

addr:SOCKADDR_IN結(jié)構(gòu)的地址。

addrlen:SOCKADDR_IN結(jié)構(gòu)長(zhǎng)度。

說(shuō)明:對(duì)于該客戶端后續(xù)的所有操作,都應(yīng)使用這個(gè)新套接字。至于原來(lái)那個(gè)套接字,它仍然用于接受其它客戶端連接,而且仍然處于監(jiān)聽狀態(tài),第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.6.2基本W(wǎng)insock函數(shù)下面的代碼說(shuō)明了accept()的調(diào)用過(guò)程。SOCKETsServSock;sockaddr_inaddr;intnSockErr,nNumConns;SOCKETsConns[5];sockaddrConnaddrs[5];intnAddrLen=sizeof(sockaddr);sServSock=socket(AF_INET,SOCK_STREAM,0);//建立socket對(duì)象addr.sin_family=AF_INET;addr.sin_port=htons(5050);//為socket分配端口addr.sin_addr.s_addr=htonl(INADDR_ANY);if(bind(sServSock,(LPSOCKADDR)&addr,sizeof(addr))==SOCKET_ERROR){ nSockErr=WSAGetLastError(); return;//Handleerror,Donotcontinue}if(listen(sServSock,2)== SOCKET_ERROR){//監(jiān)聽客戶連接請(qǐng)求

nSockErr=WSAGetLastError(); return;//處理錯(cuò)誤,不再繼續(xù)}第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.6.2基本W(wǎng)insock函數(shù)while(nNumconns<5){ sConns[nNumConns]=accept(sServSock,ConnAddrs[nNumConns],&nAddrLen);//接受連接

if(sConns[nNumConns]=INVALID_SOCKET) { nSockErr=WSAGetLastError(); return;//處理錯(cuò)誤

} else {

//新socket已經(jīng)成功地連接

StartNewHandleThread(sConns[nNumConns]); nNumConns++; }}第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.6.2基本W(wǎng)insock函數(shù)(5)connect()

功能:用于建立與一個(gè)服務(wù)器端的連接。

格式:intconnect(SOCKETs,conststructsockaddrFAR*name,intnamelen);

參數(shù)說(shuō)明:

s:標(biāo)識(shí)一個(gè)未連接套接字的描述字。

name:是針對(duì)TCP的套接字地址結(jié)構(gòu)(SOCKADDR_IN),標(biāo)識(shí)服務(wù)進(jìn)程IP地址及端口信息。

namelen:標(biāo)識(shí)name參數(shù)的長(zhǎng)度。 第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.6.2基本W(wǎng)insock函數(shù)(6)closesocket()

功能:

關(guān)閉一個(gè)套接字。

格式:

intPASCALFARclosesocket(SOCKETs);

參數(shù)s:準(zhǔn)備關(guān)閉的套接字。

注釋:closesocket的調(diào)用會(huì)釋放套接字描述字s,以后再對(duì)s的訪問(wèn)均以WSAENOTSOCK錯(cuò)誤返回。

第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.6.2基本W(wǎng)insock函數(shù)(7)shutdown()功能:禁止在一個(gè)套接字上進(jìn)行數(shù)據(jù)的接收與發(fā)送。格式:intPASCALFARshutdown(SOCKETs,inthow);

參數(shù)說(shuō)明:

s:套接字句柄。

how:標(biāo)志,用于描述禁止哪些操作??赡艿娜≈凳牵篠D_RECEIVE、SD_SEND或SD_BOTH。SD_RECEIVE表示不允許再調(diào)用接收函數(shù)。SD_SEND表示不允許再調(diào)用發(fā)送函數(shù)。SD_BOTH表示取消連接兩端的收發(fā)操作。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.6.3數(shù)據(jù)傳輸函數(shù)(1)send()功能:向一個(gè)已連接的套接字發(fā)送數(shù)據(jù)。返回發(fā)送數(shù)據(jù)的字節(jié)數(shù),若發(fā)生錯(cuò)誤,就返回SOCKET_ERROR。格式:intPASCALFARsend(SOCKETs,constcharFAR*buf,intlen,intflags);

參數(shù)說(shuō)明:

s:是已連接套接字的描述字。

buf:字符緩沖區(qū),包含待發(fā)送數(shù)據(jù)。

len:即將發(fā)送緩沖區(qū)中的字符數(shù)。

flags:調(diào)用的執(zhí)行方式??梢詾?、MSG_DONTROUTE、MSG_OOB或這些標(biāo)志按位“或”運(yùn)算的結(jié)果。MSG_DONTROUTE要求傳輸層不要路由出去,MSG_OOB標(biāo)志數(shù)據(jù)應(yīng)被帶外發(fā)送。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.6.3數(shù)據(jù)傳輸函數(shù)(2)recv()功能:從已建立連接的套接字接收數(shù)據(jù)。格式:intPASCALFARrecv(SOCKETs,charFAR*buf,intlen,intflags);參數(shù)說(shuō)明:

s:標(biāo)識(shí)已連接套接字的描述字。

buf:用于接收數(shù)據(jù)的字符緩沖區(qū)。

len:準(zhǔn)備接收的字節(jié)數(shù)或buf緩沖區(qū)長(zhǎng)度。

flags:指定調(diào)用方式??梢允?、MSG_PEEK、MSG_OOB或這些標(biāo)志按位“或”運(yùn)算的結(jié)果。0表示無(wú)特殊行為,MSG_PEEK使有用的數(shù)據(jù)復(fù)制到所提供的接收端緩沖區(qū)內(nèi),但沒(méi)有把它從系統(tǒng)緩沖區(qū)中刪除。

rec()返回發(fā)送字節(jié)數(shù)。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.6.3數(shù)據(jù)傳輸函數(shù)(3)sendto()功能:向一指定目的地發(fā)送數(shù)據(jù)。格式:intPASCALFARsendto(SOCKETs,constcharFAR*buf,intlen,intflags,conststructsockaddrFAR*to,inttolen);

參數(shù)說(shuō)明:

s:標(biāo)識(shí)套接字的描述字。

buf:待發(fā)送數(shù)據(jù)的緩沖區(qū)。

len:發(fā)送的字節(jié)數(shù)。

flags:調(diào)用方式標(biāo)志位??梢詾?、MSG_DONTROUTE、MSG_OOB或這些標(biāo)志按位“或”運(yùn)算的結(jié)果。

to:(可選)指針,指向目的套接字(SOCKADDR結(jié)構(gòu))的地址。

tolen:to所指地址結(jié)構(gòu)的長(zhǎng)度。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.6.3數(shù)據(jù)傳輸函數(shù)(4)recvfrom()功能:接收一個(gè)數(shù)據(jù)報(bào)并保存源地址。格式:intPASCALFARrecvfrom(SOCKETs,charFAR*buf,intlen,intflags,structsockaddrFAR*from,intFAR*fromlen);參數(shù)說(shuō)明

s:標(biāo)識(shí)一個(gè)已連接套接字的描述字。

buf:接收數(shù)據(jù)緩沖區(qū)。

len:準(zhǔn)備接收的字節(jié)數(shù)或buf緩沖區(qū)長(zhǎng)度。

flags:調(diào)用操作方式。可以是0、MSG_PEEK、MSG_OOB或這些標(biāo)志按位“或”運(yùn)算的結(jié)果。0表示無(wú)特殊行為,MSG_PEEK使有用的數(shù)據(jù)復(fù)制到所提供的接收端緩沖區(qū)內(nèi),但沒(méi)有把它從系統(tǒng)緩沖區(qū)中刪除。

from:(可選)指針,指向裝有源地址的緩沖區(qū)。

fromlen:(可選)指針,指向SOCKADDR地址結(jié)構(gòu)的長(zhǎng)度。函數(shù)返回時(shí),from指向的單元便填入發(fā)送數(shù)據(jù)端的地址。buf獲得接收數(shù)據(jù)。

第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.6.4字節(jié)順序及地址轉(zhuǎn)換函數(shù)(1)字節(jié)順序轉(zhuǎn)換函數(shù)

把一個(gè)數(shù)從主機(jī)字節(jié)順序轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)順序:

u_longhtonl(u_longhostlong);u_shorthtons(u_shorthostshort);

把網(wǎng)絡(luò)字節(jié)順序轉(zhuǎn)換為主機(jī)字節(jié)順序:

u_longntoh(u_longnetlong);u_shortntohs(u_shortnetshort);

第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.6.4字節(jié)順序及地址轉(zhuǎn)換函數(shù)(2)地址轉(zhuǎn)換函數(shù)inet_addr()

功能:將點(diǎn)分式IP地址轉(zhuǎn)換為一個(gè)32位的無(wú)符號(hào)長(zhǎng)整數(shù)。格式:unsignedlonginet_addr(constcharFAR*cp);cp:以Internet標(biāo)準(zhǔn)“.”間隔的IP地址字符串。這個(gè)函數(shù)的返回是一個(gè)網(wǎng)絡(luò)字節(jié)順序的32位長(zhǎng)整數(shù)。inet_ntoa()

功能:將32為無(wú)符號(hào)長(zhǎng)整數(shù)轉(zhuǎn)換為點(diǎn)分式IP地址。格式:char*inet_ntoa(structint_addrinaddr);inaddr是32為長(zhǎng)整數(shù)。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.6.5網(wǎng)絡(luò)信息查詢函數(shù)(1)getpeername()功能:獲取通信方的套接字地址信息。格式:intPASCALFARgetpeername(SOCKETs,structsockaddrFAR*name,intFAR*namelen);s:已連接的套接字。

name:接收端地址的名字結(jié)構(gòu)。

namelen:一個(gè)指向名字結(jié)構(gòu)長(zhǎng)度的指針。(2)getscokname()功能:該函數(shù)是getpeer的對(duì)應(yīng)函數(shù)。獲取指定套接字的本地地址信息。格式:intPASCALFARgetsockname(SOCKETs,structsockaddrFAR*name,intFAR*namelen);s:標(biāo)識(shí)一個(gè)已綁定套接字的描述字。

name:接收套接口的地址(名字)。

namelen:一個(gè)指向名字結(jié)構(gòu)長(zhǎng)度的指針。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.6.5網(wǎng)絡(luò)信息查詢函數(shù)(3)gethostbyname()功能:返回對(duì)應(yīng)于給定主機(jī)名的主機(jī)信息。在已知友好主機(jī)名,打算查找其IP地址的時(shí)候,可以使用這個(gè)函數(shù)。格式:structhostentFAR*gethostbyname(constcharFAR*name);name:指向主機(jī)名的指針。(4)gethostbyaddr()功能:返回對(duì)應(yīng)于給定IP地址的主機(jī)信息。在已知IP地址,打算查找其友好主機(jī)名的時(shí)候,可以使用這個(gè)函數(shù)。格式:structhostentFAR*PASCALFARgethostbyaddr(constcharFAR*addr,intlen,inttype);addr:是一個(gè)指向網(wǎng)絡(luò)字節(jié)順序IP地址的指針。len:

地址的長(zhǎng)度,在AF_INET類型地址中為4。type:地址類型,應(yīng)為AF_INET。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.6.5網(wǎng)絡(luò)信息查詢函數(shù)(5)getservbyname()功能:返回對(duì)應(yīng)于給定服務(wù)名和協(xié)議名的相關(guān)服務(wù)信息。在已知服務(wù)的情況下,要查找其對(duì)應(yīng)的端口號(hào),可以使用這個(gè)函數(shù)。格式:structserventFAR*PASCALFARgetservbyname(constcharFAR*name,constcharFAR*proto);name:一個(gè)指向服務(wù)名的指針。proto:

指向協(xié)議名的指針(可選)。如果這個(gè)指針為空,getservbyname()返回第一個(gè)name與s_name或者某一個(gè)s_aliases匹配的服務(wù)條目。否則getservbyname()對(duì)name和proto都進(jìn)行匹配。注釋:getservbyname()返回與給定服務(wù)名對(duì)應(yīng)的包含名字和服務(wù)號(hào)信息的servent結(jié)構(gòu)指針。

如果沒(méi)有錯(cuò)誤發(fā)生,getservbyname()返回如上所述的一個(gè)指向servent結(jié)構(gòu)的指針,否則,返回一個(gè)空指針。應(yīng)用程序可以通過(guò)WSAGetLastError()來(lái)得到一個(gè)特定的錯(cuò)誤代碼。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.7會(huì)話通信程序設(shè)計(jì)

會(huì)話通信程序結(jié)構(gòu)會(huì)話通信程序?qū)嵗谌禄赥CP/IP協(xié)議的網(wǎng)絡(luò)編程§3.7.1會(huì)話通信程序結(jié)構(gòu)

會(huì)話套接字定義了一種可靠的面向連接的服務(wù),實(shí)現(xiàn)了無(wú)差錯(cuò)無(wú)重復(fù)的順序數(shù)據(jù)傳輸。會(huì)話套接字的服務(wù)進(jìn)程和客戶進(jìn)程在通信前必須建立各自的套接字并建立連接,然后才能對(duì)相應(yīng)的套接字進(jìn)行“讀”、“寫”操作,實(shí)現(xiàn)數(shù)據(jù)的傳輸。在會(huì)話通信程序中使用的基本W(wǎng)insock函數(shù)有

socket、bind、listen、accept、connect、shutdown和closesocket等,使用的數(shù)據(jù)傳輸函數(shù)有send和recv。會(huì)話通信程序的步驟如下:第一步:要將指定協(xié)議的套接字綁定到它已知的名字上。這個(gè)名字就是本地的IP地址加端口號(hào)。這個(gè)過(guò)程通過(guò)bind函數(shù)來(lái)完成。第二步:服務(wù)進(jìn)程要處于監(jiān)聽狀態(tài),等待任意數(shù)量的客戶端連接,以便為它們的請(qǐng)求提供服務(wù)。服務(wù)進(jìn)程必須在所綁定的名字上進(jìn)行監(jiān)聽。因此需要把套接字置為監(jiān)聽模式。通過(guò)listen函數(shù)來(lái)實(shí)現(xiàn)。第三步:服務(wù)進(jìn)程調(diào)用函數(shù)accept或WSAAccept準(zhǔn)備接受來(lái)自客戶端的連接。如果一個(gè)客戶端這時(shí)用connnect函數(shù)試圖建立連接,服務(wù)進(jìn)程就可以接受連接。第四步:連接建立后,服務(wù)器端和客戶端之間就可以使用send和recv函數(shù)進(jìn)行通信。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.7.1會(huì)話通信程序結(jié)構(gòu)

第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程阻塞,等待用戶數(shù)據(jù)WinSock服務(wù)進(jìn)程建立套接字socket()綁定套接字bind()監(jiān)聽listen()WinSock客戶進(jìn)程建立套接字socket()準(zhǔn)備接受連接accept()建立連接connect()recv()send()請(qǐng)求數(shù)據(jù)send()rec()處理服務(wù)請(qǐng)求應(yīng)答數(shù)據(jù)關(guān)閉close()關(guān)閉close()會(huì)話套接字的編程模型§3.7.2會(huì)話通信程序?qū)嵗?/p>

該實(shí)例完成一個(gè)服務(wù)器端和客戶端簡(jiǎn)單的會(huì)話通信過(guò)程。要求主機(jī)上安裝TCP/IP協(xié)議,并設(shè)定IP地址為4。服務(wù)器端和客戶端使用同一臺(tái)主機(jī)的不同端口號(hào),服務(wù)器端使用的端口號(hào)為2000,客戶端使用的端口號(hào)為3000。

服務(wù)器端程序先運(yùn)行,首先初始化Winsock,然后創(chuàng)建套接字,在2000端口上進(jìn)行綁定,接著在2000端口進(jìn)行監(jiān)聽,并進(jìn)入等待連接狀態(tài)??蛻舳撕筮\(yùn)行,同樣首先初始化Winsock,然后創(chuàng)建套接字,接著嘗試和服務(wù)器端的連接。連接一旦建立,就可以在服務(wù)器端和客戶端之間進(jìn)行通信??蛻舳颂崾据斎胍粋€(gè)數(shù)字,比如輸入50,那么客戶端會(huì)從“data0”到“data49”發(fā)送50個(gè)字符串,輸入0退出。這個(gè)程序雖然簡(jiǎn)單,但是它卻包含了一個(gè)會(huì)話通信程序最基本的框架。程序中所包含的頭文件是Winsock程序所必須的?!癢insock.h”:Winsock頭文件,版本1.1使用Winsock.h,版本2使用Winsock2.h?!皐indows.h”:創(chuàng)建一個(gè)Windowsconsole程序所必需的頭文件。#pragmacomment(lib,"wsock32.lib"):指定連接的庫(kù)文件。版本W(wǎng)insock1.1使用wsock32.lib,版本W(wǎng)insock2使用ws2_32.lib。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.8數(shù)據(jù)報(bào)通信程序設(shè)計(jì)

數(shù)據(jù)報(bào)通信程序結(jié)構(gòu) 數(shù)據(jù)報(bào)通信實(shí)例第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.8.1數(shù)據(jù)報(bào)通信程序結(jié)構(gòu)

數(shù)據(jù)報(bào)套接字是無(wú)連接的,它的編程過(guò)程比流套接字模型要簡(jiǎn)單一些。數(shù)據(jù)報(bào)套接字編程模型使用的基本W(wǎng)insock函數(shù)和會(huì)話套接字模型一致。使用的數(shù)據(jù)傳輸函數(shù)則和會(huì)話套接字不同,發(fā)送數(shù)據(jù)用sendto函數(shù),接收數(shù)據(jù)使用revfrom函數(shù)。數(shù)據(jù)報(bào)通信程序步驟如下:第一步:服務(wù)器端和客戶端都要?jiǎng)?chuàng)建一個(gè)數(shù)據(jù)報(bào)套接字。第二步:服務(wù)器端調(diào)用bind函數(shù)給套接字分配一個(gè)公認(rèn)的端口。在開發(fā)應(yīng)用程序時(shí),這個(gè)公認(rèn)端口通常是指定的。第三步:客戶端和服務(wù)器端都可以使用sendto函數(shù)發(fā)送消息,使用recvfrom接收消息,完成數(shù)據(jù)報(bào)傳遞。最后調(diào)用closesocket關(guān)閉套接字。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.8.1數(shù)據(jù)報(bào)通信程序結(jié)構(gòu)

第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程服務(wù)器socket()

bind()recvfrom()sendto()阻塞,等待客戶數(shù)據(jù)處理服務(wù)請(qǐng)求socket()bind()sendto()recvfrom()客戶機(jī)服務(wù)請(qǐng)求服務(wù)應(yīng)答數(shù)據(jù)報(bào)套接字編程模型close()close()§3.8.2數(shù)據(jù)報(bào)通信實(shí)例

該實(shí)例完成一個(gè)服務(wù)器端和客戶端簡(jiǎn)單的數(shù)據(jù)報(bào)通信過(guò)程。要求主機(jī)上安裝TCP/IP協(xié)議,并設(shè)定IP地址為4。服務(wù)器端和客戶端使用同一臺(tái)主機(jī)的不同端口號(hào),服務(wù)器端使用的端口號(hào)為2000,客戶端使用的端口號(hào)為3000。服務(wù)器端首先初始化Winsock,然后創(chuàng)建套接字,在2000端口上進(jìn)行綁定,然后等待接收客戶端發(fā)送的數(shù)據(jù)??蛻舳撕筮\(yùn)行,同樣首先初始化Winsock,然后創(chuàng)建套接字,在3000端口上進(jìn)行綁定,然后就可以向服務(wù)器端發(fā)送數(shù)據(jù)??蛻舳颂崾景慈我怄I進(jìn)行發(fā)送,按任意鍵后,客戶端會(huì)從“data0”到“data49”發(fā)送50個(gè)字符串,再按任意鍵退出。這個(gè)程序包含了一個(gè)數(shù)據(jù)報(bào)通信程序最基本的框架。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.9Winsock多播與廣播通信程序設(shè)計(jì)

廣播通信 多播通信第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.9.1廣播通信

(1)廣播通信的實(shí)現(xiàn)

現(xiàn)在大多數(shù)網(wǎng)絡(luò)都支持廣播(broadcast)通信,但對(duì)于許多TCP/IP實(shí)現(xiàn)來(lái)說(shuō),要實(shí)現(xiàn)廣播通信,首先必須設(shè)置好子網(wǎng)掩碼和廣播地址,這樣底層網(wǎng)絡(luò)才能夠接收廣播信息。TCP/IP協(xié)議是通過(guò)IP地址來(lái)對(duì)計(jì)算機(jī)進(jìn)行識(shí)別的,IP地址分為標(biāo)識(shí)網(wǎng)絡(luò)的網(wǎng)絡(luò)標(biāo)識(shí)編碼和標(biāo)識(shí)網(wǎng)絡(luò)內(nèi)唯一主機(jī)的主機(jī)標(biāo)識(shí)編碼兩部分。廣播地址是主機(jī)標(biāo)識(shí)編碼全為1的IP地址。

使用廣播通信進(jìn)行數(shù)據(jù)通信的最大好處在于:當(dāng)多臺(tái)計(jì)算機(jī)進(jìn)行交叉數(shù)據(jù)傳送時(shí)連接數(shù)不會(huì)造成級(jí)數(shù)增長(zhǎng),數(shù)據(jù)傳輸量相對(duì)減少,參與通信的計(jì)算機(jī)數(shù)量對(duì)程序透明并且增加、減少計(jì)算機(jī)不會(huì)影響程序的執(zhí)行。此外,廣播通信是對(duì)等(peertopeer),沒(méi)有客戶和服務(wù)器之分,參與通信的計(jì)算機(jī)可以使用同一個(gè)通信程序。因此,對(duì)于可靠性要求不是很高的多機(jī)通信系統(tǒng),使用廣播通信是一個(gè)很好的解決方案。廣播通信也有其缺點(diǎn):當(dāng)廣播在整個(gè)網(wǎng)段上發(fā)送時(shí),容易引起網(wǎng)絡(luò)的阻塞。廣播數(shù)據(jù)不能越過(guò)路由器,使位于不同網(wǎng)段的計(jì)算機(jī)不能收到廣播消息。作為一種對(duì)等通信,它沒(méi)有權(quán)限設(shè)置,不利于網(wǎng)絡(luò)維護(hù)。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.9.1廣播通信

使用Winsock實(shí)現(xiàn)廣播通信一般分為五個(gè)步驟:第一步:創(chuàng)建數(shù)據(jù)報(bào)套接字。在Winsock支持的套接字中,只有數(shù)據(jù)報(bào)套接字(SOCK_DGRAM)才支持廣播通信。第二步:

綁定數(shù)據(jù)報(bào)套接字于指定的地址和端口。第三步:通過(guò)套接字選項(xiàng)設(shè)置數(shù)據(jù)報(bào)套接字的廣播屬性。intsetsockopt(SOCKETs,intlevel,intoptname,constcharFAR*optval,intoptlen);level:SOL_SOCKETorIPPROTO_TCPOptnam:SO_BROADCAST第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.9.1廣播通信

下面的程序段就是創(chuàng)建一個(gè)廣播套接字的過(guò)程:BOOLoptval=TRUE;SOCKETs;SOCKETADDR_INin;

socket(AF_INET,SOCK_DGRAM,0)//創(chuàng)建套接字in.sin_family=AF_INET;in.sin_addr.s_addr=INADDR_ANY;in.sin_port=htons(PORT);//PORT為預(yù)定義的變量if(bind(s,(LPSOCLADDR)&in,sizeof(in))){//綁定失敗

closesocket(s);returnFALSE;}if(setsockopt(s,SOL_SOCKET,SO_BROADCAST,(char*)&optval,sizeof(optval)==SOCKET_ERROR){

//套接字選項(xiàng)設(shè)置失敗

closesocket(s);returnFALSE;}

第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.9.1廣播通信第四步:通過(guò)sendto函數(shù)發(fā)送廣播信息。發(fā)送廣播信息和流套接字的數(shù)據(jù)發(fā)送不同,它只能使用sendto函數(shù),而不能使用send函數(shù)。發(fā)送地址必須為INADDR_BROADCAST(廣播地址)。下面的程序段顯示了廣播消息發(fā)送的實(shí)現(xiàn)過(guò)程:

intlength;SOCKADDRto;//發(fā)送目標(biāo)to.sin_family=AF_INET;to.sin_addr.s_addr=INADDR_BROADCAST;to.sin_port=htons(PORT);//s是通過(guò)前面三個(gè)步驟創(chuàng)建的廣播套接字描述字if((length=sendto(s,lpBuffer,len,0,(LPSOCKADDR)&to,sizeof(SOCKADDR)))==SOCKET_ERROR){

//發(fā)送失敗

closesocket(s); returnFALSE;}

第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.9.1廣播通信

第五步:接收廣播消息??梢酝ㄟ^(guò)recvfrom()函數(shù)接收廣播消息,下面一段代碼顯示了接收廣播消息的過(guò)程。interron,len,fromlen;SOCKADDR_INfrom;fromlen=sizeof(SOCKADDR)if((len=recvfrom(s,lpBuffer,length,0,(LPSOCKADDR)&from,&fromlen))==SOCKET_ERROR){//接收失敗

closesocket(s);returnFALSE;}else{//接收成功}第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.9.2多播通信

(1)概念

“多播”亦稱“多點(diǎn)傳送”(Multicasting),是一種讓數(shù)據(jù)從一個(gè)成員送出,然后復(fù)制給其他多個(gè)成員的技術(shù)。采用這種技術(shù),可有效減輕網(wǎng)絡(luò)通信的負(fù)擔(dān),避免資源的無(wú)謂浪費(fèi)。設(shè)計(jì)這一技術(shù)的目的是彌補(bǔ)“廣播”(Broadcasting)通信的不足。假如過(guò)度使用廣播技術(shù),極易造成網(wǎng)絡(luò)帶寬的大幅占用,影響整個(gè)網(wǎng)絡(luò)的通信效率。多播通信則不同。對(duì)一個(gè)網(wǎng)絡(luò)內(nèi)的工作站來(lái)說(shuō),只有在上面運(yùn)行的進(jìn)程表示自己“有興趣”,多播數(shù)據(jù)才會(huì)復(fù)制給它們。然而,并非所有協(xié)議都支持多播通信,對(duì)Win32平臺(tái)而言,僅兩種可從Winsock內(nèi)訪問(wèn)的協(xié)議(IP和ATM)才提供了對(duì)多播通信的支持。多播通信具有兩個(gè)層面的重要特征:控制層面和數(shù)據(jù)層面。其中,“控制層面”(ControlPlane)定義了組成員的組織方式;而“數(shù)據(jù)層面”(DataPlane)決定了在不同的成員之間數(shù)據(jù)如何傳送。這兩方面的特征既可以是“有根的”(Rooted),也可以是“無(wú)根的”(Nonrooted)。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.9.2多播通信

第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程有根和無(wú)根控制層模型比較邀請(qǐng)邀請(qǐng)邀請(qǐng)A有根控制層結(jié)構(gòu)B無(wú)根控制層結(jié)構(gòu)多播組根節(jié)點(diǎn)葉節(jié)點(diǎn)葉節(jié)點(diǎn)葉節(jié)點(diǎn)葉節(jié)點(diǎn)葉節(jié)點(diǎn)葉節(jié)點(diǎn)葉節(jié)點(diǎn)§3.9.2多播通信

在一個(gè)“有根的”控制層面內(nèi),存在著一個(gè)特殊的多播組成員,叫作根節(jié)點(diǎn),而剩下的每個(gè)組成員都叫作葉節(jié)點(diǎn)。大多數(shù)情況下,根節(jié)點(diǎn)需負(fù)責(zé)多播組的建立,其間涉及到建立同任意數(shù)量的葉節(jié)點(diǎn)的連接。對(duì)任何一個(gè)具體的組來(lái)說(shuō),都只能存在一個(gè)根節(jié)點(diǎn)。在有根控制層面中,根節(jié)點(diǎn)必須明確邀請(qǐng)每個(gè)葉節(jié)點(diǎn)加入該組,葉節(jié)點(diǎn)才能加入。ATM協(xié)議便是“有根控制層面”的典型例子。而對(duì)一個(gè)“無(wú)根的”控制層面來(lái)說(shuō),任何節(jié)點(diǎn)都能自由加入多播組。

第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.9.2多播通信

數(shù)據(jù)層面也存在著“有根的”和“無(wú)根的”兩種形式。對(duì)一個(gè)有根數(shù)據(jù)層面而言,它有一個(gè)參與者叫作根節(jié)點(diǎn)。數(shù)據(jù)傳輸只能在數(shù)據(jù)根和多播會(huì)話的其他所有成員葉節(jié)點(diǎn)之間進(jìn)行。這種傳輸既可單向進(jìn)行,也可雙向進(jìn)行。但既然是一個(gè)有根數(shù)據(jù)層面,很明顯出自一個(gè)葉節(jié)點(diǎn)的數(shù)據(jù)只會(huì)被根節(jié)點(diǎn)接收到;而自根節(jié)點(diǎn)發(fā)出的數(shù)據(jù)卻可由每個(gè)葉節(jié)點(diǎn)收到。在有根數(shù)據(jù)層面中,自根節(jié)點(diǎn)發(fā)出的數(shù)據(jù)會(huì)傳送給每一個(gè)葉節(jié)點(diǎn);而自一個(gè)葉節(jié)點(diǎn)發(fā)出的數(shù)據(jù)卻只會(huì)發(fā)往根節(jié)點(diǎn),不會(huì)“蔓延”到其他葉節(jié)點(diǎn)。在無(wú)根數(shù)據(jù)層面中,從任何節(jié)點(diǎn)發(fā)出的數(shù)據(jù)都會(huì)“蔓延”到整個(gè)多播組,每個(gè)節(jié)點(diǎn)對(duì)于數(shù)據(jù)的發(fā)送也沒(méi)有任何限制,可以向任何組成員發(fā)送數(shù)據(jù)。IP多播采用的就是兩個(gè)層面上的“無(wú)根”方式。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.9.2多播通信

第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程發(fā)送數(shù)據(jù)發(fā)送數(shù)據(jù)發(fā)送數(shù)據(jù)根節(jié)點(diǎn)葉節(jié)點(diǎn)葉節(jié)點(diǎn)葉節(jié)點(diǎn)……A有根數(shù)據(jù)層面數(shù)據(jù)流向數(shù)據(jù)流數(shù)據(jù)流B有根數(shù)據(jù)層面數(shù)據(jù)流向葉節(jié)點(diǎn)葉節(jié)點(diǎn)葉節(jié)點(diǎn)葉節(jié)點(diǎn)有根數(shù)據(jù)和無(wú)根數(shù)據(jù)層面數(shù)據(jù)流比較§3.9.2多播通信

多播IP地址是一個(gè)D類IP地址,范圍在到55之間。但是,其中還有許多地址是為特殊用途而保留的。比如,根本沒(méi)有使用(也不能使用),代表子網(wǎng)內(nèi)的所有系統(tǒng)(主機(jī)),而代表子網(wǎng)內(nèi)的所有路由器。在實(shí)際應(yīng)用中,可使用除這三個(gè)保留多播地址之外的任何地址。為了支持多播,專門引入了一個(gè)特殊的協(xié)議(InternetGatewayManagementProtocol,IGMP

),以便管理多播客戶機(jī),以及它們?cè)诮M內(nèi)的成員關(guān)系。多播主機(jī)利用IGMP通知路由器,路由器所在子網(wǎng)的一臺(tái)計(jì)算機(jī)想加入一個(gè)特定的多播組。IGMP是IP多播方案的基礎(chǔ)。要想使它正常工作,兩個(gè)多播節(jié)點(diǎn)之間的所有路由器都必須提供對(duì)IGMP的支持。若一個(gè)應(yīng)用加入了多播組,一條IGMP“加入”命令便會(huì)發(fā)給子網(wǎng)上那個(gè)特殊的“所有路由器”地址()。該命令用于通知所有路由器,有客戶機(jī)對(duì)一個(gè)特定的多播地址產(chǎn)生了興趣,即它想加入那個(gè)多播組。以后,假如路由器收到了發(fā)給這個(gè)多播地址的數(shù)據(jù),便會(huì)將其轉(zhuǎn)發(fā)給所有多播客戶機(jī)。

第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.9.2多播通信

如果一個(gè)端點(diǎn)加入多播組,便會(huì)同時(shí)指定一個(gè)“存在時(shí)間”(TTL)參數(shù)。通過(guò)該參數(shù),我們便知道對(duì)于在端點(diǎn)機(jī)器上運(yùn)行的多播應(yīng)用程序來(lái)說(shuō),為了收發(fā)數(shù)據(jù),中途需要經(jīng)歷多少個(gè)路由器。例如,假定我們編寫了一個(gè)IP多播應(yīng)用,令其加入組Group,同時(shí)TTL值設(shè)為3。這時(shí),一個(gè)加入命令會(huì)傳給本地子網(wǎng)上的“所有路由器”組。子網(wǎng)內(nèi)的路由器會(huì)根據(jù)這一命令,判斷出自己以后應(yīng)將多播數(shù)據(jù)轉(zhuǎn)發(fā)到那個(gè)地址。隨后,路由器會(huì)將TTL值減1,再將一條加入命令傳給與自己相鄰的各個(gè)網(wǎng)絡(luò)。那些網(wǎng)絡(luò)上的路由器會(huì)如法炮制,最后又將TTL值減去1,直到TTL值已經(jīng)變成了0,該命令不會(huì)再繼續(xù)傳遞下去(不再傳給相鄰的網(wǎng)絡(luò))。從中可以看出,TTL實(shí)際限制了多播數(shù)據(jù)能夠蔓延得多“遠(yuǎn)”。

第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.9.2多播通信

(2)Winsock多播通信的實(shí)現(xiàn)

針對(duì)IP多播,Winsock提供了兩種不同的實(shí)現(xiàn)方法,具體取決于使用的是哪個(gè)版本的Winsock。第一種方法是Winsock1提供的,要求通過(guò)套接字選項(xiàng)來(lái)加入一個(gè)組。Winsock2則引入了一個(gè)新函數(shù),專門負(fù)責(zé)多播組的加入。這個(gè)函數(shù)便是WSAJoinLeaf,它與基層協(xié)議是無(wú)關(guān)的。下面,我們只介紹Winsock1方法,這也是應(yīng)用得最廣的一種方法(特別由于它是自Berkeley套接字衍生出來(lái)的)。Winsock1中,實(shí)現(xiàn)IP多播通信所需的基本步驟:第一步:用socket函數(shù)創(chuàng)建一個(gè)套接字,注意要設(shè)為AF_INET地址家族以及SOCK_DGRAM套接字類型。初始化一個(gè)多播套接字,不必設(shè)置任何特殊標(biāo)志,因?yàn)閟ocket函數(shù)本身便沒(méi)有提供什么標(biāo)志參數(shù)。第二步:如果想從組內(nèi)接收數(shù)據(jù),將套接字同一個(gè)本地端口綁定到一起。第三步:調(diào)用setsockopt函數(shù),同時(shí)設(shè)置IP_ADD_MEMBERSHIP選項(xiàng),指定想加入的那個(gè)組的地址結(jié)構(gòu)。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.9.2多播通信

假如一個(gè)應(yīng)用程序只是打算發(fā)送數(shù)據(jù),便不必加入一個(gè)IP多播組。向多播組發(fā)送數(shù)據(jù)時(shí),網(wǎng)絡(luò)中傳輸?shù)臄?shù)據(jù)包與普通UDP包大致相同,只是目的地址換成了一個(gè)特殊的多播地址而已。但假如想接收多播數(shù)據(jù),便必須加入一個(gè)組。但是除了對(duì)組成員資格的要求之外,IP多播通信與普通的UDP協(xié)議通信并無(wú)什么區(qū)別:兩者都是無(wú)連接的、不可靠的。在Winsock1中,IP多播組的加入和離開是用setsockopt命令來(lái)完成的,同時(shí)要用到IP_ADD_MEMBERSHIP(加入組)和IP_DROP_MEMBERSHIP(脫離組)這兩個(gè)選項(xiàng)。使用這兩個(gè)套接字選項(xiàng)時(shí),必須傳遞一個(gè)ip_mreq結(jié)構(gòu),它的定義如下:structip_mreq{structin_addrimr_multiaddr;//指定要加入的多播組

structin_addrimr_interface;}imr_interface:指定要通過(guò)它送出多播數(shù)據(jù)的本地(或本機(jī))接口。如果將imr_interface設(shè)為INADDR_ANY,便會(huì)自動(dòng)使用默認(rèn)接口;否則,請(qǐng)指定本地接口具體要使用哪個(gè)IP地址(假如同時(shí)有多個(gè)IP地址可選)。

第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.9.2多播通信

下面的程序段展示了如何加入一個(gè)多播組:SOCKETs;structip_mreqipmr;SOCKETADDR_INlocal;intlen=sizeof(ipmr);s=socket(AF_INET,SOCK_DGRAM,0);

local.sin_family=AF_INET;local.sin_addr.s_addr=htonl(INADDR_ANY);local.sin_port=htons(10000);ipmr.imr_multiaddr.s_addr=inet_addr(“”);ipmr.imr_interface.s_addr=htonl(INADDR_ANY);bind(s,(SOCKETADDR*)&local,sizeof(local));setsockopt(s,IPPROTO_IP,IP_ADD_MEMBERSHIP,(char*)&ipmr,&len);第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.9.2多播通信

要離開一個(gè)多播組,只需調(diào)用setsockopt,同時(shí)設(shè)置IP_DROP_MEMBRSHIP。注意仍然要傳遞一個(gè)ip_mreq結(jié)構(gòu),其中的值與加入那個(gè)組時(shí)是一樣的。如下所示:setsockopt(s,,IPPROTO_IP,IP_DROP_MEMBRSHIP,(char*)&ipmr,&len);

另外需要強(qiáng)調(diào)的是,采用廣播方式也能實(shí)現(xiàn)組播。采用的方法是選用特定的子網(wǎng)編址作為廣播地址,這樣就可以在該子網(wǎng)內(nèi)部實(shí)現(xiàn)廣播通信,從整個(gè)網(wǎng)絡(luò)來(lái)看,就實(shí)現(xiàn)了組播。第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.9.2多播通信

(3)組播專用套接字選項(xiàng)IP_MULTICAST_TTL該選項(xiàng)用于設(shè)置多播數(shù)據(jù)的TTL(存在時(shí)間)值。默認(rèn)情況下,TTL=1。也就是說(shuō),多播數(shù)據(jù)不允許傳出本地網(wǎng)絡(luò)之外,即只有同一個(gè)網(wǎng)絡(luò)內(nèi)的多播成員才會(huì)收到數(shù)據(jù)。假如增大TTL的值,多播數(shù)據(jù)就可經(jīng)歷多個(gè)路由器傳到其他網(wǎng)絡(luò)。路由器每收到一個(gè)數(shù)據(jù)包,并判斷出自己應(yīng)將這個(gè)包轉(zhuǎn)發(fā)給相鄰的網(wǎng)絡(luò),那么TTL值隨即會(huì)被減1。若減1之后,發(fā)現(xiàn)TTL的新值變成了0,路由器便會(huì)將這個(gè)包即時(shí)地丟棄。若多播數(shù)據(jù)報(bào)的目標(biāo)地址在到55之間,那么多播路由器不會(huì)對(duì)其進(jìn)行轉(zhuǎn)發(fā),無(wú)論它們的TTL有多大。這個(gè)地址范圍是為路由協(xié)議以及其他低級(jí)拓?fù)洳檎液途S護(hù)協(xié)議(比如網(wǎng)關(guān)查找和組成員關(guān)系報(bào)告)所保留的,不可擅用。若調(diào)用setsockopt,level參數(shù)便是IPPROTO_IP,optname參數(shù)是IP_MULTICAST_TTL,而optval參數(shù)是一個(gè)整數(shù),用于指定新的TTL值。例如:intoptval=8;setsockopt(s,IPPROTO_IP,IP_MULTICAST_TTL,(char*)optval,sizeof(int))第三章基于TCP/IP協(xié)議的網(wǎng)絡(luò)編程§3.9.2多播通信

IP_MULTICAST_LOOP該選項(xiàng)決定了應(yīng)用程序是否接收自己的多播數(shù)據(jù)。如應(yīng)用程序加入了一個(gè)多播組,并向那個(gè)組發(fā)送數(shù)據(jù),應(yīng)用程序便會(huì)接收到那些數(shù)據(jù)。數(shù)據(jù)送出的時(shí)候,假如有一個(gè)recvfrom調(diào)用正處于“待決”狀態(tài),調(diào)用便會(huì)返回那個(gè)數(shù)據(jù)的一個(gè)副本。要注意的是,若只是想讓應(yīng)用程序?qū)?shù)據(jù)發(fā)給一個(gè)多播組,那么它并不一定非要加入多播組。只有在希望接收發(fā)給那個(gè)組的數(shù)據(jù)時(shí),才需要加入那個(gè)組。設(shè)計(jì)IP_MUTLICAST_LOOP套接字選項(xiàng)的目的便是禁止將數(shù)據(jù)返還給本地接口。使用這個(gè)選項(xiàng),我們可將一個(gè)整數(shù)值作為op

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(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)論