版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院第第2章章 UNIX中的套接字網(wǎng)絡(luò)編程接口中的套接字網(wǎng)絡(luò)編程接口lUNIX套接字網(wǎng)絡(luò)編程接口的產(chǎn)生與發(fā)展過(guò)程l套接字與UNIX操作系統(tǒng)的關(guān)系l套接字編程的基本概念l套接字的特點(diǎn)、應(yīng)用場(chǎng)合、使用的數(shù)據(jù)類型l面向連接的套接字編程l套接字的工作過(guò)程、系統(tǒng)調(diào)用、編程實(shí)例l借助實(shí)例分析進(jìn)程的阻塞問(wèn)題和對(duì)策l無(wú)連接的套接字編程l無(wú)連接套接字編程的兩種模式(C/S和對(duì)等)l數(shù)據(jù)報(bào)套接字的對(duì)等模式編程實(shí)例 吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院2.1 UNIX套接字網(wǎng)絡(luò)編程接口的產(chǎn)生與發(fā)展套接字網(wǎng)絡(luò)編程接口的產(chǎn)生與發(fā)展2.1.1 問(wèn)題的提出問(wèn)題的提出l應(yīng)用程序與協(xié)議軟件進(jìn)行交互時(shí)須說(shuō)
2、明許多細(xì)節(jié)應(yīng)用程序與協(xié)議軟件進(jìn)行交互時(shí)須說(shuō)明許多細(xì)節(jié):l是服務(wù)器還是客戶機(jī),主動(dòng)還是被動(dòng)通信?l發(fā)送方需說(shuō)明發(fā)送的數(shù)據(jù);l接收方需說(shuō)明接收的數(shù)據(jù)如何存放。l站在應(yīng)用程序?qū)崿F(xiàn)的角度,應(yīng)用程序如何方便地使用協(xié)議棧軟件進(jìn)行通信呢?l如果能在應(yīng)用程序與協(xié)議棧軟件之間提供一個(gè)軟件接口,就可以方便客戶與服務(wù)器軟件的編程。lUNIX最早將最早將TCP/IP協(xié)議簇集成到內(nèi)核中,協(xié)議簇集成到內(nèi)核中,UNIX的開(kāi)發(fā)者提出并實(shí)現(xiàn)了套接字應(yīng)用編程接口。的開(kāi)發(fā)者提出并實(shí)現(xiàn)了套接字應(yīng)用編程接口。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院l套接字應(yīng)用程序編程接口:套接字應(yīng)用程序編程接口:是網(wǎng)絡(luò)應(yīng)用程序通過(guò)網(wǎng)是網(wǎng)絡(luò)應(yīng)用程序通過(guò)網(wǎng)絡(luò)協(xié)議
3、棧進(jìn)行通信時(shí)所使用的接口,即應(yīng)用程序與絡(luò)協(xié)議棧進(jìn)行通信時(shí)所使用的接口,即應(yīng)用程序與協(xié)議棧軟件之間的接口,簡(jiǎn)稱協(xié)議棧軟件之間的接口,簡(jiǎn)稱套接字編程接口套接字編程接口(Socket API)。l定義了應(yīng)用程序與協(xié)議棧軟件進(jìn)行交互時(shí)可以使用的一組操作,決定了應(yīng)用程序使用協(xié)議棧的方式、應(yīng)用程序所能實(shí)現(xiàn)的功能、以及開(kāi)發(fā)具有這些功能的程序的難度。l套接字編程接口給出了應(yīng)用程序能夠調(diào)用的一組過(guò)程,以及這些過(guò)程所需的參數(shù),每個(gè)獨(dú)立的過(guò)程完成一個(gè)與協(xié)議棧軟件交互的基本操作(如:建立連接、接收數(shù)據(jù)、釋放鏈接)。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院2.1.2 套接字編程接口的起源與應(yīng)用套接字編程接口的起源與應(yīng)用l加州大
4、學(xué)伯克利分校開(kāi)發(fā)了一個(gè)包括TCP/IP協(xié)議簇的BSD UNIX,并迅速得到推廣,套接字編程接口是這個(gè)操作系統(tǒng)的一部分。lTCP/IP標(biāo)準(zhǔn)并沒(méi)有定義應(yīng)用程序用來(lái)與該協(xié)議進(jìn)標(biāo)準(zhǔn)并沒(méi)有定義應(yīng)用程序用來(lái)與該協(xié)議進(jìn)行交互的應(yīng)用程序編程接口,只規(guī)定了應(yīng)該提供行交互的應(yīng)用程序編程接口,只規(guī)定了應(yīng)該提供的一般操作,并允許各個(gè)操作系統(tǒng)去定義用來(lái)實(shí)的一般操作,并允許各個(gè)操作系統(tǒng)去定義用來(lái)實(shí)現(xiàn)這些操作的具體現(xiàn)這些操作的具體API。l一個(gè)協(xié)議標(biāo)準(zhǔn)可能只是建議某個(gè)操作在應(yīng)用程序發(fā)送數(shù)據(jù)時(shí)是需要的,而由應(yīng)用程序編程接口來(lái)定義具體的函數(shù)名和每個(gè)參數(shù)的類型。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院l盡管協(xié)議標(biāo)準(zhǔn)允許操作系統(tǒng)設(shè)計(jì)者開(kāi)發(fā)
5、自己的應(yīng)盡管協(xié)議標(biāo)準(zhǔn)允許操作系統(tǒng)設(shè)計(jì)者開(kāi)發(fā)自己的應(yīng)用程序編程接口,但由于用程序編程接口,但由于BSD UNIX的廣泛使用,的廣泛使用,后來(lái)的許多操作系統(tǒng)及編程語(yǔ)言都選擇了對(duì)套接后來(lái)的許多操作系統(tǒng)及編程語(yǔ)言都選擇了對(duì)套接字編程接口的支持。字編程接口的支持。l由于這個(gè)套接字規(guī)范最早是由由于這個(gè)套接字規(guī)范最早是由Berkeley大學(xué)開(kāi)發(fā)的,大學(xué)開(kāi)發(fā)的,一般將它稱為一般將它稱為Berkeley Sockets規(guī)范。規(guī)范。lBerkeley Sockets規(guī)范規(guī)定了一系列與套接字使用有關(guān)的庫(kù)函數(shù),為在UNIX操作系統(tǒng)下不同計(jì)算機(jī)中的應(yīng)用程序進(jìn)程之間,使用TCP/IP協(xié)議簇進(jìn)行網(wǎng)絡(luò)通信提供了一套應(yīng)用程序編
6、程接口。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院2.1.3 套接字編程接口的兩種實(shí)現(xiàn)方式套接字編程接口的兩種實(shí)現(xiàn)方式l采用兩種實(shí)現(xiàn)套接字編程接口的方式:采用兩種實(shí)現(xiàn)套接字編程接口的方式:l在操作系統(tǒng)的內(nèi)核中增加相應(yīng)的軟件來(lái)實(shí)現(xiàn);l通過(guò)開(kāi)發(fā)操作系統(tǒng)之外的函數(shù)庫(kù)來(lái)實(shí)現(xiàn)。 l在在BSD UNIX及起源于它的操作系統(tǒng)中,套接字函數(shù)是及起源于它的操作系統(tǒng)中,套接字函數(shù)是操作系統(tǒng)本身的功能調(diào)用,是操作系統(tǒng)內(nèi)核的一部分。操作系統(tǒng)本身的功能調(diào)用,是操作系統(tǒng)內(nèi)核的一部分。l其他操作系統(tǒng)供應(yīng)商為了不修改基本操作系統(tǒng),開(kāi)發(fā)了其他操作系統(tǒng)供應(yīng)商為了不修改基本操作系統(tǒng),開(kāi)發(fā)了套接字庫(kù)(套接字庫(kù)(Socket Library)來(lái)
7、提供套接字編程接口。)來(lái)提供套接字編程接口。l套接字庫(kù)中的每個(gè)過(guò)程具有與UNIX套接字函數(shù)相同的名字與參數(shù),向沒(méi)有本機(jī)套接字的操作系統(tǒng)上的應(yīng)用程序提供套接字編程接口。l套接字庫(kù)與操作系統(tǒng)內(nèi)核中實(shí)現(xiàn)的套接字套接字庫(kù)與操作系統(tǒng)內(nèi)核中實(shí)現(xiàn)的套接字在語(yǔ)義在語(yǔ)義上是相同的上是相同的。l應(yīng)用程序調(diào)用套接字過(guò)程不必管它是由操作系統(tǒng)內(nèi)核過(guò)程提供的,還是由庫(kù)過(guò)程提供的。l這種方式提供了程序的可移植性:將程序從一臺(tái)計(jì)算機(jī)移植到另一臺(tái)計(jì)算機(jī)時(shí),程序的源代碼不需改動(dòng),只要用新計(jì)算機(jī)上的套接字庫(kù)重新編譯即可。l套接字庫(kù)與操作系統(tǒng)直接提供的本機(jī)套接字編程套接字庫(kù)與操作系統(tǒng)直接提供的本機(jī)套接字編程接口接口在實(shí)現(xiàn)上是不同的在
8、實(shí)現(xiàn)上是不同的。l套接字庫(kù)的過(guò)程需要鏈接到應(yīng)用程序中;l并駐留于應(yīng)用程序地址空間;l調(diào)用時(shí)控制從應(yīng)用程序轉(zhuǎn)向庫(kù)程序,并進(jìn)一步調(diào)用一個(gè)或多個(gè)底層操作系統(tǒng)的功能調(diào)用。2.1.4 套接字通信與套接字通信與UNIX操作系統(tǒng)的輸入操作系統(tǒng)的輸入/輸出輸出l套接字編程接口采用傳統(tǒng)的套接字編程接口采用傳統(tǒng)的UNIX輸入輸入/輸出模式。輸出模式。lUNIX操作系統(tǒng)對(duì)文件和所有其它操作系統(tǒng)對(duì)文件和所有其它的輸入的輸入/輸出設(shè)備輸出設(shè)備采用一種統(tǒng)一的操作模式,就是采用一種統(tǒng)一的操作模式,就是“打開(kāi)打開(kāi)-讀讀-寫寫-關(guān)閉關(guān)閉”(open - read - write - close)的的I/O模式。模式。l調(diào)用op
9、en命令獲得對(duì)指定文件或設(shè)備的使用權(quán),并返回一個(gè)用來(lái)標(biāo)識(shí)該文件或設(shè)備的短整型描述符,作為用戶在打開(kāi)的文件或設(shè)備上進(jìn)行I/O的句柄。l多次調(diào)用read或write命令來(lái)傳輸數(shù)據(jù),期間用描述符作為命令的參數(shù),指明要操作的對(duì)象。l傳輸完成后調(diào)用close命令,通知操作系統(tǒng)已經(jīng)完成了對(duì)某對(duì)象的調(diào)用,釋放所占用的資源。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院l當(dāng)當(dāng)TCP/IP協(xié)議被集成到協(xié)議被集成到UNIX內(nèi)核中的時(shí)候,相當(dāng)內(nèi)核中的時(shí)候,相當(dāng)于在于在UNIX系統(tǒng)中引入了一種新型的系統(tǒng)中引入了一種新型的I/O操作。操作。l應(yīng)用程序通過(guò)網(wǎng)絡(luò)協(xié)議棧來(lái)交換數(shù)據(jù)。l操作系統(tǒng)和應(yīng)用程序都將套接字編程接口也看作一操作系統(tǒng)和應(yīng)
10、用程序都將套接字編程接口也看作一種輸入種輸入/輸出機(jī)制。輸出機(jī)制。l操作過(guò)程類似,創(chuàng)建套接字-使用-刪除;l操作方法類似,申請(qǐng)生成一個(gè)套接字后,系統(tǒng)返回一個(gè)短整型描述符來(lái)標(biāo)識(shí)這個(gè)套接字對(duì)象;l使用的過(guò)程名可以是相同的,如write過(guò)程可以將數(shù)據(jù)發(fā)送給另一個(gè)程序、文件或網(wǎng)絡(luò)中的另一個(gè)進(jìn)程。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院lUNIX系統(tǒng)對(duì)于各種系統(tǒng)對(duì)于各種I/O的集成提供了靈活性。的集成提供了靈活性。l應(yīng)用程序可以編寫成向任何地方傳輸數(shù)據(jù),取決于描述符對(duì)象代表什么(設(shè)備、文件、套接字)。l系統(tǒng)對(duì)套接字和其它I/O使用相同的描述符空間,使得單個(gè)應(yīng)用程序既可以進(jìn)行網(wǎng)絡(luò)通信,又可以實(shí)現(xiàn)本地?cái)?shù)據(jù)傳輸。l用
11、戶進(jìn)程與網(wǎng)絡(luò)協(xié)議的交互,實(shí)際要比用戶進(jìn)程與用戶進(jìn)程與網(wǎng)絡(luò)協(xié)議的交互,實(shí)際要比用戶進(jìn)程與傳統(tǒng)傳統(tǒng)I/O設(shè)備的交互復(fù)雜得多。設(shè)備的交互復(fù)雜得多。l僅提供open、read、write、close四個(gè)過(guò)程遠(yuǎn)不夠.l使用套接字的應(yīng)用程序必須說(shuō)明許多細(xì)節(jié)。使用套接字的應(yīng)用程序必須說(shuō)明許多細(xì)節(jié)。l應(yīng)用程序使用的協(xié)議簇、遠(yuǎn)程計(jì)算機(jī)的地址、該應(yīng)用程序是客戶機(jī)還是服務(wù)器、希望的服務(wù)類型是面向連接的還是無(wú)連接的,等等。l為了提供這些細(xì)節(jié),每個(gè)套接字有許多參數(shù)與為了提供這些細(xì)節(jié),每個(gè)套接字有許多參數(shù)與選項(xiàng),需要應(yīng)用程序提供具體值。選項(xiàng),需要應(yīng)用程序提供具體值。l為避免單個(gè)套接字函數(shù)參數(shù)過(guò)多,套接字編程接口的設(shè)計(jì)者定
12、義了多個(gè)函數(shù)。l例如,創(chuàng)建套接字時(shí),先調(diào)用一個(gè)函數(shù)創(chuàng)建套接字,再調(diào)用其它函數(shù)說(shuō)明使用套接字的細(xì)節(jié)。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院2.2 套接字編程的基本概念套接字編程的基本概念圖圖2.1 電插座與電話插座的作用電插座與電話插座的作用2.2.1 什么是套接字(什么是套接字(SOCKET) l套接字是對(duì)網(wǎng)絡(luò)中不同主機(jī)上應(yīng)用進(jìn)程之間進(jìn)行雙向套接字是對(duì)網(wǎng)絡(luò)中不同主機(jī)上應(yīng)用進(jìn)程之間進(jìn)行雙向通信的端點(diǎn)的抽象。通信的端點(diǎn)的抽象。l一個(gè)套接字就是網(wǎng)絡(luò)上進(jìn)程通信的一端,提供了應(yīng)用一個(gè)套接字就是網(wǎng)絡(luò)上進(jìn)程通信的一端,提供了應(yīng)用層進(jìn)程利用網(wǎng)絡(luò)協(xié)議棧交換數(shù)據(jù)的機(jī)制層進(jìn)程利用網(wǎng)絡(luò)協(xié)議棧交換數(shù)據(jù)的機(jī)制。 吉林大學(xué)軟件學(xué)
13、院吉林大學(xué)軟件學(xué)院圖圖2.2 應(yīng)用進(jìn)程、套接口、網(wǎng)絡(luò)協(xié)議棧及操作系統(tǒng)的關(guān)系應(yīng)用進(jìn)程、套接口、網(wǎng)絡(luò)協(xié)議棧及操作系統(tǒng)的關(guān)系 l兩個(gè)應(yīng)用進(jìn)程只要分別連接到自己的套接字,就可以通過(guò)網(wǎng)絡(luò)痛惜,不用去管復(fù)雜的網(wǎng)絡(luò)結(jié)構(gòu)及數(shù)據(jù)傳輸過(guò)程。l從多個(gè)層面來(lái)理解套接字這個(gè)概念的內(nèi)涵從多個(gè)層面來(lái)理解套接字這個(gè)概念的內(nèi)涵l從所處的地位來(lái)講,套接字上聯(lián)應(yīng)用進(jìn)程,下聯(lián)網(wǎng)絡(luò)協(xié)議棧,是應(yīng)用程序通過(guò)網(wǎng)絡(luò)協(xié)議棧進(jìn)行通信的接口,是應(yīng)用程序與網(wǎng)絡(luò)協(xié)議棧交互的接口. l從實(shí)現(xiàn)的角度來(lái)講,非常復(fù)雜。套接字是一個(gè)復(fù)雜的軟件機(jī)構(gòu),包含了一定的數(shù)據(jù)結(jié)構(gòu),包含許多選項(xiàng),由操作系統(tǒng)內(nèi)核管理。l從使用的角度來(lái)講,非常簡(jiǎn)單。對(duì)套接字的操作形成了一種網(wǎng)絡(luò)應(yīng)
14、用程序的編程接口(API),提供了一組系統(tǒng)調(diào)用或庫(kù)函數(shù),可以用于構(gòu)造套接字、安裝綁定套接字、連接套接字、通過(guò)套接字交換數(shù)據(jù)、關(guān)閉套接字,實(shí)現(xiàn)各種分布式應(yīng)用。是一套操作套接字的編程接口函數(shù),是一套操作套接字的編程接口函數(shù),套接字是它的操作對(duì)象。套接字是它的操作對(duì)象。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院2.2.2 套接字的特點(diǎn)套接字的特點(diǎn)1 1通信域通信域l通信域:通信域:是一個(gè)計(jì)算機(jī)網(wǎng)絡(luò)的范圍,在這個(gè)范圍中,所有的計(jì)算機(jī)使用同一種網(wǎng)絡(luò)體系結(jié)構(gòu)及協(xié)議棧。l套接字存在于通信域中。套接字存在于通信域中。l套接字通常只和同一域中的套接字交換數(shù)據(jù)。l如果數(shù)據(jù)交換要穿越域的邊界,就一定要執(zhí)行某種解釋程序。l這里
15、,僅僅針對(duì)這里,僅僅針對(duì)Internet域,并且使用域,并且使用Internet協(xié)協(xié)議族(即議族(即TCP/IP協(xié)議族)來(lái)通信。協(xié)議族)來(lái)通信。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院2 2套接字具有三種類型套接字具有三種類型l每一個(gè)正被使用的套接字都有它確定的類型。l只有相同類型的套接字才能相互通信。(1) 數(shù)據(jù)報(bào)套接字(數(shù)據(jù)報(bào)套接字(Datagram SOCKET)l數(shù)據(jù)報(bào)套接字提供無(wú)連接的、不保證可靠的、獨(dú)數(shù)據(jù)報(bào)套接字提供無(wú)連接的、不保證可靠的、獨(dú)立的數(shù)據(jù)報(bào)傳輸服務(wù)。立的數(shù)據(jù)報(bào)傳輸服務(wù)。l在在Internet通信域中,數(shù)據(jù)報(bào)套接字使用通信域中,數(shù)據(jù)報(bào)套接字使用UDP數(shù)據(jù)數(shù)據(jù)報(bào)協(xié)議形成的進(jìn)程間通路
16、,具有報(bào)協(xié)議形成的進(jìn)程間通路,具有UDP協(xié)議為上層協(xié)議為上層所提供的服務(wù)的所有特點(diǎn)。所提供的服務(wù)的所有特點(diǎn)。l一般用于輕載通信,并具有多播通信的能力。一般用于輕載通信,并具有多播通信的能力。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院圖圖2.3 在在Internet通信域中,數(shù)據(jù)報(bào)套接字基于通信域中,數(shù)據(jù)報(bào)套接字基于UDP協(xié)議協(xié)議 吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院(2) 流式套接字(流式套接字(Stream SOCKET)l流式套接字提供雙向的、有序的、無(wú)重復(fù)的、無(wú)流式套接字提供雙向的、有序的、無(wú)重復(fù)的、無(wú)記錄邊界的可靠的數(shù)據(jù)流傳輸服務(wù)。記錄邊界的可靠的數(shù)據(jù)流傳輸服務(wù)。l在在Internet通信域中,流式
17、套接字使用通信域中,流式套接字使用TCP協(xié)議形協(xié)議形成的進(jìn)程間通路,具有成的進(jìn)程間通路,具有TCP協(xié)議為上層所提供的協(xié)議為上層所提供的服務(wù)的所有特點(diǎn)。服務(wù)的所有特點(diǎn)。l在使用流式套接字傳輸數(shù)據(jù)之前,必須在數(shù)據(jù)的在使用流式套接字傳輸數(shù)據(jù)之前,必須在數(shù)據(jù)的發(fā)送端和接收端之間建立連接。發(fā)送端和接收端之間建立連接。 l一般用于交換大批量的數(shù)據(jù)時(shí),或者要求數(shù)據(jù)按一般用于交換大批量的數(shù)據(jù)時(shí),或者要求數(shù)據(jù)按照發(fā)送的順序無(wú)重復(fù)的到達(dá)目的地的時(shí)候。照發(fā)送的順序無(wú)重復(fù)的到達(dá)目的地的時(shí)候。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院圖圖2.4 在在Internet通信域中,流式套接字基于通信域中,流式套接字基于TCP協(xié)議協(xié)議吉
18、林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院(3) 原始式套接字(原始式套接字(RAW SOCKET)l原始式套接字允許對(duì)較低層次的協(xié)議原始式套接字允許對(duì)較低層次的協(xié)議(如如IP、ICMP)直接訪問(wèn),用于檢驗(yàn)新協(xié)議的實(shí)現(xiàn)。直接訪問(wèn),用于檢驗(yàn)新協(xié)議的實(shí)現(xiàn)。l原始套接字保存了數(shù)據(jù)包中的完整IP頭;l前面兩種套接字只能收到用戶數(shù)據(jù);l因此可以通過(guò)原始套接字對(duì)數(shù)據(jù)進(jìn)行分析。 吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院3 3套接字的創(chuàng)建套接字的創(chuàng)建l套接字由應(yīng)用層的通信進(jìn)程創(chuàng)建,并為其服務(wù)。套接字由應(yīng)用層的通信進(jìn)程創(chuàng)建,并為其服務(wù)。l即,每一個(gè)套接字都有一個(gè)相關(guān)的應(yīng)用進(jìn)程,操作即,每一個(gè)套接字都有一個(gè)相關(guān)的應(yīng)用進(jìn)程,操作該套接
19、字的代碼是該進(jìn)程的組成部分。該套接字的代碼是該進(jìn)程的組成部分。 4 4使用確定的使用確定的IPIP地址和傳輸層端口號(hào)地址和傳輸層端口號(hào)l在生成套接字的描述符后,要將套接字與計(jì)算機(jī)上在生成套接字的描述符后,要將套接字與計(jì)算機(jī)上的特定的的特定的IP地址和傳輸層端口號(hào)相關(guān)聯(lián),這個(gè)過(guò)程地址和傳輸層端口號(hào)相關(guān)聯(lián),這個(gè)過(guò)程稱為稱為綁定綁定。l 一個(gè)套接口要使用一個(gè)確定的三元組網(wǎng)絡(luò)地址信息,一個(gè)套接口要使用一個(gè)確定的三元組網(wǎng)絡(luò)地址信息,才能使它在網(wǎng)絡(luò)中唯一地被標(biāo)識(shí)。才能使它在網(wǎng)絡(luò)中唯一地被標(biāo)識(shí)。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院2.2.3 套接字的應(yīng)用場(chǎng)合套接字的應(yīng)用場(chǎng)合l并非所有的網(wǎng)絡(luò)應(yīng)用編程都要使用套接字
20、。并非所有的網(wǎng)絡(luò)應(yīng)用編程都要使用套接字。l套接字適合開(kāi)發(fā)具有如下特點(diǎn)的新網(wǎng)絡(luò)應(yīng)用。套接字適合開(kāi)發(fā)具有如下特點(diǎn)的新網(wǎng)絡(luò)應(yīng)用。l不管是采用對(duì)等模式或者客戶機(jī)/服務(wù)器模式,通信雙方的應(yīng)用程序都需要開(kāi)發(fā)。l雙方所交換數(shù)據(jù)的結(jié)構(gòu)和交換數(shù)據(jù)的順序有特定的要求,不符合現(xiàn)在成熟的應(yīng)用層協(xié)議,甚至需要自己去開(kāi)發(fā)應(yīng)用層協(xié)議,自己設(shè)計(jì)最適合的數(shù)據(jù)結(jié)構(gòu)和信息交換規(guī)程。 l套接字編程層次較低,自由度較大。套接字編程層次較低,自由度較大。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院2.2.4 套接字使用的數(shù)據(jù)類型和相關(guān)的問(wèn)題套接字使用的數(shù)據(jù)類型和相關(guān)的問(wèn)題1 1三種表示套接字地址的結(jié)構(gòu)三種表示套接字地址的結(jié)構(gòu)l在套接字編程接口中,定
21、義了三種結(jié)構(gòu)型的數(shù)據(jù)類型,在套接字編程接口中,定義了三種結(jié)構(gòu)型的數(shù)據(jù)類型,用來(lái)存儲(chǔ)協(xié)議相關(guān)的網(wǎng)絡(luò)地址,在套接字編程接口的用來(lái)存儲(chǔ)協(xié)議相關(guān)的網(wǎng)絡(luò)地址,在套接字編程接口的函數(shù)調(diào)用中要用到它們。函數(shù)調(diào)用中要用到它們。(1) sockaddr結(jié)構(gòu):結(jié)構(gòu):針對(duì)各種通信域的套接字,用來(lái)表示地址的一般格式,然后要求每個(gè)協(xié)議族說(shuō)明其協(xié)議地址如果具體使用這個(gè)一般格式的。struct sockaddr u_charsa_len; / 地址總長(zhǎng)u_char sa_family; / 地址家族charsa_data14; / 協(xié)議地址 (2) sockaddr_in結(jié)構(gòu):結(jié)構(gòu):專門針對(duì)Internet通信域,存儲(chǔ)套接
22、字相關(guān)的網(wǎng)絡(luò)地址信息,例如IP地址,傳輸層端口號(hào)等信息。struct sockaddr_in u_charsa_len; / 地址總長(zhǎng)u_char sin_family;/ 地址家族,必須設(shè)定為u_shortsin_port;/ 端口號(hào),2字節(jié)struct in_addr sin_addr;/ IP 地址,4字節(jié)charsin_zero8;/ 未用,全為0 ,8字節(jié) (3) in_addr結(jié)構(gòu):結(jié)構(gòu):專門用來(lái)存儲(chǔ) IP地址。Struct in_addr Unsigned long s_addrl;AF_INET14字節(jié)字節(jié)(4) 這些數(shù)據(jù)結(jié)構(gòu)的一般用法這些數(shù)據(jù)結(jié)構(gòu)的一般用法l首先,定義一個(gè)首先
23、,定義一個(gè)sockaddr_in的結(jié)構(gòu)實(shí)例,并將它清的結(jié)構(gòu)實(shí)例,并將它清零。零。struct sockaddr_in myad;memset(&myad,0,sizeof(struct sockaddr_in); l然后,為這個(gè)結(jié)構(gòu)賦值。然后,為這個(gè)結(jié)構(gòu)賦值。myad.sin_family=AF_INET;myad.sin_port=htons(8080); myad.sin_addr.s_addr=htonl(INADDR-ANY);l第三步,在函數(shù)調(diào)用中使用時(shí),將這個(gè)結(jié)構(gòu)強(qiáng)制轉(zhuǎn)第三步,在函數(shù)調(diào)用中使用時(shí),將這個(gè)結(jié)構(gòu)強(qiáng)制轉(zhuǎn)換為換為sockaddr類型。類型。accept(listen
24、fd,(sockaddr*)(&myad),&addrlen); 吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院2 2本機(jī)字節(jié)順序和網(wǎng)絡(luò)字節(jié)順序本機(jī)字節(jié)順序和網(wǎng)絡(luò)字節(jié)順序l本機(jī)字節(jié)順序:本機(jī)字節(jié)順序:在具體計(jì)算機(jī)中的多字節(jié)數(shù)據(jù)的存在具體計(jì)算機(jī)中的多字節(jié)數(shù)據(jù)的存儲(chǔ)順序。儲(chǔ)順序。l網(wǎng)絡(luò)字節(jié)順序:網(wǎng)絡(luò)字節(jié)順序:多字節(jié)數(shù)據(jù)在網(wǎng)絡(luò)協(xié)議報(bào)頭中的存多字節(jié)數(shù)據(jù)在網(wǎng)絡(luò)協(xié)議報(bào)頭中的存儲(chǔ)順序。儲(chǔ)順序。l網(wǎng)絡(luò)應(yīng)用程序要在不同的計(jì)算機(jī)中運(yùn)行,本機(jī)字節(jié)網(wǎng)絡(luò)應(yīng)用程序要在不同的計(jì)算機(jī)中運(yùn)行,本機(jī)字節(jié)順序是不同的,但網(wǎng)絡(luò)字節(jié)順序是一定的。順序是不同的,但網(wǎng)絡(luò)字節(jié)順序是一定的。l所以,在應(yīng)用程序編程的時(shí)候,在把所以,在應(yīng)用程序
25、編程的時(shí)候,在把IP地址和端口地址和端口號(hào)裝入套接字時(shí),應(yīng)當(dāng)把它們從本機(jī)字節(jié)順序轉(zhuǎn)換號(hào)裝入套接字時(shí),應(yīng)當(dāng)把它們從本機(jī)字節(jié)順序轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)順序;相反,在本機(jī)輸出時(shí),應(yīng)將它們?yōu)榫W(wǎng)絡(luò)字節(jié)順序;相反,在本機(jī)輸出時(shí),應(yīng)將它們從網(wǎng)絡(luò)字節(jié)順序轉(zhuǎn)換為本機(jī)字節(jié)順序。從網(wǎng)絡(luò)字節(jié)順序轉(zhuǎn)換為本機(jī)字節(jié)順序。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院l套接字編程接口為解決這個(gè)問(wèn)題設(shè)置了四個(gè)函數(shù):套接字編程接口為解決這個(gè)問(wèn)題設(shè)置了四個(gè)函數(shù):lhtons() 短整數(shù)本機(jī)順序轉(zhuǎn)換為網(wǎng)絡(luò)順序,用于端口號(hào)。lhtonl() 長(zhǎng)整數(shù)本機(jī)順序轉(zhuǎn)換為網(wǎng)絡(luò)順序,用于IP地址。lntohs() 短整數(shù)網(wǎng)絡(luò)順序轉(zhuǎn)換為本機(jī)順序,用于端口號(hào)。lntohl
26、() 長(zhǎng)整數(shù)網(wǎng)絡(luò)順序轉(zhuǎn)化為本機(jī)順序,用于IP地址。l這四個(gè)函數(shù)將被轉(zhuǎn)換的數(shù)值作為函數(shù)的參數(shù),函數(shù)這四個(gè)函數(shù)將被轉(zhuǎn)換的數(shù)值作為函數(shù)的參數(shù),函數(shù)返回值是轉(zhuǎn)換后的結(jié)果。返回值是轉(zhuǎn)換后的結(jié)果。 吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院3 3點(diǎn)分十進(jìn)制的點(diǎn)分十進(jìn)制的IPIP地址的轉(zhuǎn)換地址的轉(zhuǎn)換l在因特網(wǎng)中,IP地址常用點(diǎn)分十進(jìn)制的表示方法,在套接字中,IP地址是無(wú)符號(hào)的長(zhǎng)整型數(shù),套接字接口設(shè)置了兩個(gè)函數(shù)用于兩種形式IP地址的轉(zhuǎn)換。(1) inet-addr函數(shù)函數(shù)unsigned long inet-addr( const char* cp)l入口參數(shù)入口參數(shù)cp:點(diǎn)分十進(jìn)制形式的:點(diǎn)分十進(jìn)制形式的IP地址。地
27、址。l返回值:返回值: 網(wǎng)絡(luò)字節(jié)順序的網(wǎng)絡(luò)字節(jié)順序的IP地址,是無(wú)符號(hào)的長(zhǎng)地址,是無(wú)符號(hào)的長(zhǎng)整數(shù)。整數(shù)。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院(2) inet_ntoa函數(shù)函數(shù)char* inet_ntoa(struct in_addr in)l入口參數(shù)入口參數(shù)in:包含長(zhǎng)整型:包含長(zhǎng)整型IP地址的地址的 in_addr 結(jié)構(gòu)變結(jié)構(gòu)變量;量;l返回值:返回值: 指向點(diǎn)分十進(jìn)制指向點(diǎn)分十進(jìn)制IP地址的字符串的指針地址的字符串的指針. 吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院4 4域名服務(wù)域名服務(wù)l通常,我們使用域名來(lái)標(biāo)識(shí)站點(diǎn),可以將文字型的主機(jī)域名直接轉(zhuǎn)換成IP地址。struct hostent* getho
28、stbyname( const char* name);l入口參數(shù):是站點(diǎn)的主機(jī)域名字符串;入口參數(shù):是站點(diǎn)的主機(jī)域名字符串;l返回值:返回值:是指向是指向hostent 結(jié)構(gòu)的指針。結(jié)構(gòu)的指針。lhostent結(jié)構(gòu)包含主機(jī)名、主機(jī)別名數(shù)組、返回地址的類型(一般是AF-INET)、地址長(zhǎng)度的字節(jié)數(shù)、已符合網(wǎng)絡(luò)字節(jié)順序的主機(jī)網(wǎng)絡(luò)地址等。 吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院2.3 面向連接的套接字編程面向連接的套接字編程2.3.1 套接字的工作過(guò)程套接字的工作過(guò)程l面向連接的通信方式基于面向連接的通信方式基于TCP,必須借助流式套,必須借助流式套接字來(lái)編程,應(yīng)用服務(wù)器分為服務(wù)器端和客戶端,接字來(lái)編程
29、,應(yīng)用服務(wù)器分為服務(wù)器端和客戶端,雙方是不對(duì)稱的,需要分別編程。雙方是不對(duì)稱的,需要分別編程。l雙方首先要?jiǎng)?chuàng)建并安裝套接字,做好準(zhǔn)備;l建立連接,采用三次握手的方式;l數(shù)據(jù)交換,稱為客戶機(jī)與服務(wù)器的會(huì)話期,會(huì)話的內(nèi)容必須遵守一定的格式和順序;l釋放連接。l下面介紹面向連接的服務(wù)器和客戶端的編程步驟下面介紹面向連接的服務(wù)器和客戶端的編程步驟.吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院2.3.2 UNIX套接字編程接口的系統(tǒng)調(diào)用套接字編程接口的系統(tǒng)調(diào)用1創(chuàng)建套接字創(chuàng)建套接字SOCKET()l創(chuàng)建一個(gè)套接字,并返回一個(gè)整型描述符:創(chuàng)建一個(gè)套接字,并返回一個(gè)整型描述符:int SOCKET( int Proto
30、family, int Type, int Protocol); l入口參數(shù):入口參數(shù):lProtofamily:套接字使用的協(xié)議簇,一般為PF_INET,表示TCP/IP協(xié)議簇,PF_DECnet表示DEC協(xié)議。 ltype:套接字類型,SOCK_STREMA表示創(chuàng)建面向連接的流傳輸?shù)牧魇教捉幼?;SOCK_DGRAMA表示創(chuàng)建無(wú)連接的面向消息的數(shù)據(jù)報(bào)套接字。 lprotocol:套接字使用的傳輸層網(wǎng)絡(luò)協(xié)議,一般為IPPROTO_IP,internet通信域中一般取值為0。 吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院l返回值:返回值:l套接字創(chuàng)建成功,返回一個(gè)int型的整數(shù),即所創(chuàng)建套接字的描述符,指向
31、被維護(hù)在操作系統(tǒng)內(nèi)核里的socket數(shù)據(jù)結(jié)構(gòu)。l套接字創(chuàng)建出錯(cuò),返回1,表示出錯(cuò)類型的代碼保存在全局變量Errno中。l舉例:舉例:int sockfd=SOCKET(PF_INTE,SOCK_STREAM,0)l創(chuàng)建套接字時(shí),為其分配了內(nèi)存,并建立了相應(yīng)的數(shù)據(jù)結(jié)構(gòu),用于指定連接的種類和使用的協(xié)議,同時(shí)還有關(guān)于連接隊(duì)列操作的選項(xiàng)結(jié)構(gòu)字段,創(chuàng)建時(shí)設(shè)置為默認(rèn)值。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院2綁定套接字到指定的地址綁定套接字到指定的地址 BIND()lint BIND( int Sockfd, struct sockaddr* My_addr, int Addrlen); l入口參數(shù):入口參數(shù):
32、lSockfd:是由SOCKET()系統(tǒng)調(diào)用創(chuàng)建的套接字描述符,要將其綁定到指定的網(wǎng)絡(luò)地址上;lMy_addr:指向sockaddr結(jié)構(gòu)變量的指針,所指結(jié)構(gòu)中保存著特定的網(wǎng)絡(luò)地址,要將套接字綁定到這個(gè)網(wǎng)絡(luò)地址上;lAddlen:是sockaddr結(jié)構(gòu)的長(zhǎng)度。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院l返回值:返回值:l如果返回0,表示已經(jīng)綁定成功。l如果返回1,表示有錯(cuò),出錯(cuò)碼在Errno中。l舉例:舉例:Struct sockaddr_in my_addr;if( BIND(sockfd, (sockaddr*)&my_addr ,sizeof(struct sockaddr_in) )0 )
33、 報(bào)錯(cuò),并退出l在服務(wù)器端,用作監(jiān)聽(tīng)客戶機(jī)連接請(qǐng)求的套接字一定要綁定,因?yàn)榇蠖鄶?shù)服務(wù)器進(jìn)程使用熟知端口,并且服務(wù)器有時(shí)有多塊網(wǎng)卡,會(huì)有多個(gè)IP地址。l客戶機(jī)一般不用綁定。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院l返回值:返回值:l如果返回0,表示已經(jīng)綁定成功。l如果返回1,表示有錯(cuò),出錯(cuò)碼在Errno中。l服務(wù)器調(diào)用BIND,來(lái)說(shuō)明它將用來(lái)接收通信的協(xié)議端口號(hào),同時(shí)my_addr 結(jié)構(gòu)中還包含記錄IP地址的域,此時(shí)如果主機(jī)是多宿主機(jī),則in_addr字段取值常量INADDR_ANY,允許服務(wù)器在該計(jì)算機(jī)的任何IP地址上使用一個(gè)指定的端口。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院3啟動(dòng)監(jiān)聽(tīng)啟動(dòng)監(jiān)聽(tīng)Listen(
34、)lint LISTEN( int Sockfd, int Queuesize);l入口參數(shù):入口參數(shù):lSockfd:套接字描述符,通過(guò)它來(lái)監(jiān)聽(tīng)來(lái)自客戶機(jī)端的連接請(qǐng)求。lQueuesize:等待連接隊(duì)列的最大長(zhǎng)度,最大可設(shè)為20,一般設(shè)為510。(操作系統(tǒng)為每個(gè)監(jiān)聽(tīng)套接字建立一個(gè)用來(lái)等待連接的“先進(jìn)先出”緩沖區(qū)隊(duì)列,若緩沖區(qū)隊(duì)列有空就接收一個(gè)客戶端請(qǐng)求。)l返回值:返回值:l函數(shù)正確執(zhí)行則返回0,出錯(cuò)則返回-1。l舉例:舉例:LISTEN(Sockfe,10);l本套接字只適用于面向連接的流式套接字。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院舉例:舉例:LISTEN(Sockfe, 10); 圖圖2.
35、6 監(jiān)聽(tīng)套接字使用緩沖區(qū)接納多個(gè)客戶端的連接請(qǐng)求監(jiān)聽(tīng)套接字使用緩沖區(qū)接納多個(gè)客戶端的連接請(qǐng)求 吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院4接收連接請(qǐng)求接收連接請(qǐng)求ACCEPT()lint ACCEPT(int Sockfd, struct sockaddr* Addr, int* addrlen);l入口參數(shù):入口參數(shù):lSockfd:監(jiān)聽(tīng)客戶端連接請(qǐng)求的套接字描述符。lAddr:sockaddr結(jié)構(gòu)變量的指針,是一個(gè)出口參數(shù),當(dāng)調(diào)用執(zhí)行完畢時(shí),變量中放置的是所接收客戶機(jī)端的網(wǎng)絡(luò)地址。lAddrlen:整型變量指針,也是一個(gè)出口參數(shù),調(diào)用時(shí)初始設(shè)置為Addr結(jié)構(gòu)的長(zhǎng)度,不能為0或null,調(diào)用執(zhí)行完畢時(shí)
36、,返回所接收的客戶機(jī)端網(wǎng)絡(luò)地址長(zhǎng)度。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院l返回值:返回值:l如果執(zhí)行正確,返回一個(gè)新的套接字描述符,這個(gè)套接字已經(jīng)與客戶機(jī)端建立了連接,并專用于此后與客戶機(jī)端交換數(shù)據(jù)。l如果出錯(cuò),返回1。l說(shuō)明:說(shuō)明:l調(diào)用從監(jiān)聽(tīng)套接字的等待隊(duì)列中,取出第一個(gè)連接請(qǐng)求,創(chuàng)建一個(gè)新的套接字,并通過(guò)這個(gè)新套接字向客戶機(jī)端發(fā)送連接應(yīng)答,從而與客戶機(jī)端建立連接,系統(tǒng)為這個(gè)新的套接字分配一個(gè)服務(wù)器端的自由端口號(hào),這個(gè)套接字用于后續(xù)與客戶機(jī)端交換數(shù)據(jù),稱為響應(yīng)套接字。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院l本調(diào)用僅適用于面向連接的流式套接字,與LISTEN()配套使用,兩個(gè)入口參數(shù)能返回客戶端的網(wǎng)絡(luò)
37、地址.l本調(diào)用以阻塞的方式工作,若監(jiān)聽(tīng)套接字的等待隊(duì)列為空,則本調(diào)用就阻塞直到有連接請(qǐng)求的到來(lái)。l舉例:int clientfd; / 定義響應(yīng)套接字描述符變量int addrlen=sizeof(sockaddr); / 獲得套接字地址結(jié)構(gòu)長(zhǎng)度。struct sockaddr_in cltsockaddr; / 定義用于返回客戶端地址的結(jié)構(gòu)。clientfd=ACCEPT(listenfd, (sockaddr* )(&cltsockaddr), &addrlen); / 接收客戶連接請(qǐng)求 吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院5請(qǐng)求建立連接請(qǐng)求建立連接CONNECT()lint
38、CONNECT( int Sockfd, struct sockaddr* Service_addr, int Addrlen);l入口參數(shù):入口參數(shù):lSockfd:客戶機(jī)端的請(qǐng)求套接字;lService_addr:存放服務(wù)器端的網(wǎng)絡(luò)地址;lAddrlen:sockaddr結(jié)構(gòu)的長(zhǎng)度。l返回值:返回值:l連接成功,返回0;l連接未成功,返回-1。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院l說(shuō)明:說(shuō)明:l用于客戶端請(qǐng)求連接到服務(wù)器;l對(duì)于流式套接字,使用傳輸層TCP協(xié)議,服務(wù)器若接受連接請(qǐng)求,即把它放入監(jiān)聽(tīng)套接字的緩沖區(qū)隊(duì)列,并調(diào)用ACCEPT()來(lái)接收處理;l對(duì)于數(shù)據(jù)報(bào)套接字,使用傳輸層UDP協(xié)議,并
39、不建立連接,而只是將套接字置為connected的狀態(tài),客戶機(jī)向同一服務(wù)器傳送多條信息時(shí),意義在于使用CONNECT在套接字中記錄服務(wù)器的地址,允許客戶機(jī)只指明服務(wù)器地址一次,而不必在每條信息中都指明目的地址。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院l舉例:舉例: if ( CONNECT(sockfd, (struct sockaddr*)(&serv_addr), sizeof(struct sockaddr) ) 0 ) 報(bào)錯(cuò),并退出吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院6讀讀/寫套接字寫套接字READ()和和WRITE()lint READ( int sockfd, void* buffer
40、, int len )lint WRITE( int sockfd, void* buffer, int len )l入口參數(shù):入口參數(shù):lSockfd:要讀/寫的套接字描述符,在客戶機(jī)端是請(qǐng)求套接字,在服務(wù)器端是響應(yīng)套接字;lBuffer:字符串變量的指針,指向內(nèi)存中用來(lái)存放數(shù)據(jù)的讀寫緩沖區(qū),讀套接字時(shí)存放從套接字接收到的數(shù)據(jù),寫套接字的時(shí)候存放要發(fā)送的數(shù)據(jù);lLen:讀寫緩沖區(qū)的長(zhǎng)度。l返回值:返回值:l對(duì)于read()返回實(shí)際讀到的字符數(shù)。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院l說(shuō)明:說(shuō)明:l套接字起源于UNIX,UNIX將套接字也統(tǒng)一使用read和write對(duì)I/O操作進(jìn)行數(shù)據(jù)傳輸。l優(yōu)點(diǎn):
41、普遍性,應(yīng)用程序能夠創(chuàng)建一個(gè)發(fā)往或接收自一個(gè)描述符的數(shù)據(jù)傳輸,而不必知道這個(gè)描述符對(duì)應(yīng)的是一個(gè)文件還是一個(gè)套接字。l缺點(diǎn):套接字庫(kù)的實(shí)現(xiàn)可能對(duì)所有使用套接字的應(yīng)用增加額外的I/O開(kāi)銷。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院7發(fā)送發(fā)送 SEND() 和接收和接收 RECV()int SEND( int sockfd, char* buf, int len, int flags );int RECV( int sockfd, char* buf, int len, int flags ); l入口參數(shù):入口參數(shù):lsockfd:用來(lái)發(fā)送/接收數(shù)據(jù)的套接字描述符,可以是由SOCKET()創(chuàng)建的,也可以是A
42、CCEPT()返回的;lbuf:用于發(fā)送/接收數(shù)據(jù)的緩沖區(qū)指針;llen:要發(fā)送的或接收到的字符數(shù);lflags:執(zhí)行本調(diào)用的方式,一般置為0.吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院l返回值:返回值:l處理錯(cuò)誤,返回-1;l如果正確,對(duì)于發(fā)送返回實(shí)際發(fā)送出去的字節(jié)數(shù);對(duì)于接收返回實(shí)際讀入緩沖區(qū)的字節(jié)數(shù)。l說(shuō)明:說(shuō)明:l和read、write一樣,必須用于已連接的套接字,無(wú)需調(diào)用者指明目的地參數(shù)。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院l8關(guān)閉套接字關(guān)閉套接字CLOSE() int CLOSE( int sockfd ); l入口參數(shù):入口參數(shù):lsockfd:要關(guān)閉的套接字描述符。l說(shuō)明:說(shuō)明:l如果是面向
43、連接的,CLOSE在關(guān)閉套接字前先終止連接;l關(guān)閉一個(gè)套接字意味著立即終止對(duì)它的使用,描述符被釋放,以防止應(yīng)用程序發(fā)送或接收更多的數(shù)據(jù)。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院2.3.3 面向連接的套接字編程實(shí)例面向連接的套接字編程實(shí)例1實(shí)例的功能實(shí)例的功能l服務(wù)器對(duì)來(lái)訪的客戶計(jì)數(shù),并向客戶報(bào)告這個(gè)計(jì)數(shù)值服務(wù)器對(duì)來(lái)訪的客戶計(jì)數(shù),并向客戶報(bào)告這個(gè)計(jì)數(shù)值; ;l客戶建立與服務(wù)器的一個(gè)連接并等待它的輸出;客戶建立與服務(wù)器的一個(gè)連接并等待它的輸出;l每當(dāng)連接請(qǐng)求到達(dá)時(shí),服務(wù)器生成一個(gè)可打印的每當(dāng)連接請(qǐng)求到達(dá)時(shí),服務(wù)器生成一個(gè)可打印的ASCIIASCII串信息,將它在連接上發(fā)回,然后關(guān)閉連接;串信息,將它在連接
44、上發(fā)回,然后關(guān)閉連接;l客戶顯示收到的信息,然后退出??蛻麸@示收到的信息,然后退出。l例如,對(duì)于服務(wù)器接收的第10次客戶連接請(qǐng)求,該客戶將收到并打印如下信息:This server has been contacted 10 times. 吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院2實(shí)例程序的命令行參數(shù)實(shí)例程序的命令行參數(shù)l實(shí)例是實(shí)例是UNIX環(huán)境下的環(huán)境下的C程序,客戶和服務(wù)器程序程序,客戶和服務(wù)器程序在編譯后,均以命令行的方式執(zhí)行。在編譯后,均以命令行的方式執(zhí)行。l服務(wù)器程序執(zhí)行時(shí)可以帶一個(gè)命令行參數(shù),用來(lái)服務(wù)器程序執(zhí)行時(shí)可以帶一個(gè)命令行參數(shù),用來(lái)接收請(qǐng)求的監(jiān)聽(tīng)套接字的協(xié)議端口號(hào)。接收請(qǐng)求的監(jiān)聽(tīng)套接
45、字的協(xié)議端口號(hào)。l這個(gè)參數(shù)是可選的,如果不指定端口號(hào),代碼將使用程序內(nèi)定的缺省端口號(hào)5188。l客戶程序執(zhí)行時(shí)可以帶兩個(gè)命令行參數(shù):客戶程序執(zhí)行時(shí)可以帶兩個(gè)命令行參數(shù):l一個(gè)是服務(wù)器所在計(jì)算機(jī)的主機(jī)名;l另一個(gè)是服務(wù)器監(jiān)聽(tīng)的協(xié)議端口號(hào)。吉林大學(xué)軟件學(xué)院吉林大學(xué)軟件學(xué)院l這兩個(gè)參數(shù)都是可選的。l如果沒(méi)有指定協(xié)議端口號(hào),客戶使用程序內(nèi)定的缺省值5188。l如果一個(gè)參數(shù)也沒(méi)有,客戶使用缺省端口和主機(jī)名localhost,localhost是映射到客戶所運(yùn)行的計(jì)算機(jī)的一個(gè)別名。l允許客戶與本地機(jī)上的服務(wù)器通信,對(duì)調(diào)試是很允許客戶與本地機(jī)上的服務(wù)器通信,對(duì)調(diào)試是很有用的。有用的。 3客戶程序代碼客戶程序
46、代碼/*-* 程序:程序: client.c* 目的:目的: 創(chuàng)建一個(gè)套接字,通過(guò)網(wǎng)絡(luò)連接一個(gè)服務(wù)器,并打印來(lái)創(chuàng)建一個(gè)套接字,通過(guò)網(wǎng)絡(luò)連接一個(gè)服務(wù)器,并打印來(lái)自服務(wù)器的信息自服務(wù)器的信息* 語(yǔ)法:語(yǔ)法: client host port * host - 運(yùn)行服務(wù)器的計(jì)算機(jī)的名字運(yùn)行服務(wù)器的計(jì)算機(jī)的名字* port - 服務(wù)器監(jiān)聽(tīng)套接字所用協(xié)議端口號(hào)服務(wù)器監(jiān)聽(tīng)套接字所用協(xié)議端口號(hào)* 注意:兩個(gè)參數(shù)都是可選的。如果未指定主機(jī)名,客戶使用注意:兩個(gè)參數(shù)都是可選的。如果未指定主機(jī)名,客戶使用localhost;如果未指定端口號(hào),;如果未指定端口號(hào), * 客戶將使用客戶將使用PROTOPORT中給定的
47、缺省協(xié)議端口號(hào)中給定的缺省協(xié)議端口號(hào)*-*/ #include /* 基本系統(tǒng)數(shù)據(jù)類型基本系統(tǒng)數(shù)據(jù)類型*/#include /* UNIX下,套接字接口包含文件下,套接字接口包含文件*/#include /* Internet地址簇地址簇*/#include /* Internet定義定義*/#include /* 網(wǎng)絡(luò)數(shù)據(jù)庫(kù)操作網(wǎng)絡(luò)數(shù)據(jù)庫(kù)操作*/#include /* 標(biāo)準(zhǔn)輸入輸出標(biāo)準(zhǔn)輸入輸出*/#include /* 字符串處理字符串處理*/#define PROTOPORT 5188 /*缺省協(xié)議端口號(hào)缺省協(xié)議端口號(hào)*/extern int errno;char localhost =
48、“l(fā)ocalhost”; /*缺省主機(jī)名缺省主機(jī)名*/ main(argc,argv)int argc;char *argv;struct hostent *ptrh; /* 指向主機(jī)列表中一個(gè)條目的指針指向主機(jī)列表中一個(gè)條目的指針 */struct sockaddr_in servaddr; /* 存放服務(wù)器端網(wǎng)絡(luò)地址的結(jié)構(gòu)存放服務(wù)器端網(wǎng)絡(luò)地址的結(jié)構(gòu) */intsockfd; /* 客戶端的套接字描述符客戶端的套接字描述符 */intport; /* 服務(wù)器端套接字協(xié)議端口號(hào)服務(wù)器端套接字協(xié)議端口號(hào)*/char* host; /* 服務(wù)器主機(jī)名指針?lè)?wù)器主機(jī)名指針 */int n; /* 讀
49、取的字符數(shù)讀取的字符數(shù) */char buf1000 ; /* 緩沖區(qū),接收服務(wù)器發(fā)來(lái)的數(shù)據(jù)緩沖區(qū),接收服務(wù)器發(fā)來(lái)的數(shù)據(jù) */ memset(char*)& servaddr,0,sizeof(servaddr); /* 清空清空sockaddr結(jié)構(gòu)結(jié)構(gòu) */servaddr.sin_family = AF_INET; /* 設(shè)置為因特網(wǎng)協(xié)議族設(shè)置為因特網(wǎng)協(xié)議族 */ /* 檢查命令行參數(shù),如果有,就抽取端口號(hào)。否則使用內(nèi)定的缺省值檢查命令行參數(shù),如果有,就抽取端口號(hào)。否則使用內(nèi)定的缺省值*/if (argc2) port = atoi(argv2); /* 如果指定了協(xié)議端口,就轉(zhuǎn)換
50、成整數(shù)如果指定了協(xié)議端口,就轉(zhuǎn)換成整數(shù) */else port = PROTOPORT; /* 否則,使用缺省端口號(hào)否則,使用缺省端口號(hào) */if (port0) /* 如果端口號(hào)是合法的數(shù)值,就將它裝入網(wǎng)絡(luò)地址結(jié)構(gòu)如果端口號(hào)是合法的數(shù)值,就將它裝入網(wǎng)絡(luò)地址結(jié)構(gòu) */ servaddr.sin_port = htons(u_short)port);else /* 否則,打印錯(cuò)誤信息并退出否則,打印錯(cuò)誤信息并退出*/fprintf(stderr,”bad port number %sn”,argv2);exit(1); /* 檢查主機(jī)參數(shù)并指定主機(jī)名檢查主機(jī)參數(shù)并指定主機(jī)名 */if(argc1
51、)host = argv1; /* 如果指定了主機(jī)名參數(shù),就使用它如果指定了主機(jī)名參數(shù),就使用它 */elsehost = localhost; /* 否則,使用缺省值否則,使用缺省值 */ /* 將主機(jī)名轉(zhuǎn)換成相應(yīng)的將主機(jī)名轉(zhuǎn)換成相應(yīng)的IP地址并復(fù)制到地址并復(fù)制到servaddr 結(jié)構(gòu)中結(jié)構(gòu)中 */* 從服務(wù)器主機(jī)名得到相應(yīng)的從服務(wù)器主機(jī)名得到相應(yīng)的IP地址地址 */ptrh = gethostbyname( host ); if ( (char *)ptrh = null ) /* 檢查主機(jī)名的有效性,無(wú)效則退出檢查主機(jī)名的有效性,無(wú)效則退出 */ fprintf( stderr, ”in
52、valid host: %sn”, host ); exit(1);memcpy(&servaddr.sin_addr, ptrh-h_addr, ptrh-h_length ); Struct hostent char *h_name; char *h_aliases; int h_addrtype; int h_length; char *h_addr_list; ; /* 創(chuàng)建一個(gè)套接字創(chuàng)建一個(gè)套接字*/sockfd = SOCKET(AF_INET, SOCK_STREAM, 0);if (sockfd 0) fprintf(stderr, ”socket creation f
53、ailedn” ); exit(1);/* 請(qǐng)求連接到服務(wù)器請(qǐng)求連接到服務(wù)器 */if (connect( sockfd, (struct sockaddr *)& servaddr, sizeof(servaddr) 0) write(1,buf, n); n = recv( sockfd , buf, sizeof( buf ), 0 ); /* 關(guān)閉套接字關(guān)閉套接字*/closesocket( sockfd ); /* 終止客戶程序終止客戶程序*/exit(0); 4服務(wù)器實(shí)例代碼服務(wù)器實(shí)例代碼/*-* 程序:程序:server.c* 目的:目的: 分配一個(gè)套接字,然后反復(fù)執(zhí)行如
54、下幾步:分配一個(gè)套接字,然后反復(fù)執(zhí)行如下幾步:* (1) 等待客戶的下一個(gè)連接等待客戶的下一個(gè)連接* (2) 發(fā)送一個(gè)短消息給客戶發(fā)送一個(gè)短消息給客戶* (3) 關(guān)閉與客戶的連接關(guān)閉與客戶的連接* (4) 轉(zhuǎn)向(轉(zhuǎn)向(1)步)步* 命令行語(yǔ)法:命令行語(yǔ)法: server port * port 服務(wù)器端監(jiān)聽(tīng)套接字使用的協(xié)議端口號(hào)服務(wù)器端監(jiān)聽(tīng)套接字使用的協(xié)議端口號(hào)* 注意:注意: 端口號(hào)可選。如果未指定端口號(hào),服務(wù)器使用端口號(hào)可選。如果未指定端口號(hào),服務(wù)器使用PROTOPORT中指定的缺省中指定的缺省* 端口號(hào)端口號(hào)*-*/ #include #include #include #include
55、 #include #include #define PROTOPORT 5188 /* 監(jiān)聽(tīng)套接字的缺省協(xié)議端口號(hào)監(jiān)聽(tīng)套接字的缺省協(xié)議端口號(hào) */#define QLEN 6 /* 監(jiān)聽(tīng)套接字的請(qǐng)求隊(duì)列大小監(jiān)聽(tīng)套接字的請(qǐng)求隊(duì)列大小 */int visits = 0; /* 對(duì)于客戶連接的計(jì)數(shù)對(duì)于客戶連接的計(jì)數(shù)*/ main(argc,argc)int argc;char* argv;struct hostent *ptrh; /* 指向主機(jī)列表中一個(gè)條目的指針指向主機(jī)列表中一個(gè)條目的指針 */struct sockaddr_in servaddr; /* 存放服務(wù)器網(wǎng)絡(luò)地址的結(jié)構(gòu)存放服務(wù)器網(wǎng)
56、絡(luò)地址的結(jié)構(gòu) */struct sockaddr_in clientaddr; /* 存放客戶網(wǎng)絡(luò)地址的結(jié)構(gòu)存放客戶網(wǎng)絡(luò)地址的結(jié)構(gòu) */int listenfd; /* 監(jiān)聽(tīng)套接字描述符監(jiān)聽(tīng)套接字描述符 */int clientfd; /* 響應(yīng)套接字描述符響應(yīng)套接字描述符 */int port; /* 協(xié)議端口號(hào)協(xié)議端口號(hào) */int alen; /* 地址長(zhǎng)度地址長(zhǎng)度 */char buf1000; /* 供服務(wù)器發(fā)送字符串所用的緩沖區(qū)供服務(wù)器發(fā)送字符串所用的緩沖區(qū) */ /* 清空清空sockaddr結(jié)構(gòu)結(jié)構(gòu) */memset( (char*)& servaddr, 0, siz
57、eof(servaddr) ); servaddr.sin_family = AF_INET; /* 設(shè)置為因特網(wǎng)協(xié)議族設(shè)置為因特網(wǎng)協(xié)議族 */servaddr.sin_addr.s_addr = INADDR_ANY; /* 設(shè)置本地設(shè)置本地IP地址地址 */ /* 檢查命令行參數(shù),若已指定,則使用該端口號(hào),否則使用缺省端口號(hào)檢查命令行參數(shù),若已指定,則使用該端口號(hào),否則使用缺省端口號(hào) */if (argc 1) port = atoi(argv1); /* 如果指定了端口號(hào),就將它轉(zhuǎn)換成整數(shù)如果指定了端口號(hào),就將它轉(zhuǎn)換成整數(shù) */ else port = PROTOPORT; /* 否則,
58、使用缺省端口號(hào)否則,使用缺省端口號(hào) */ if (port 0) /* 測(cè)試端口號(hào)是否合法測(cè)試端口號(hào)是否合法 */servaddr.sin_port=htons( (u_short)port );else /* 打印錯(cuò)誤信息并退出打印錯(cuò)誤信息并退出 */ fprintf( stderr, ”bad port number %sn”, argv1 ); exit(1); /* 創(chuàng)建一個(gè)用于監(jiān)聽(tīng)的流式套接字創(chuàng)建一個(gè)用于監(jiān)聽(tīng)的流式套接字 */listenfd = SOCKET(AF_INET,SOCK_STREAM,0);if (listenfd 0) fprintf( stderr, “socke
59、t creation failedn” ); exit(1); /* 將本地地址綁定到監(jiān)聽(tīng)套接字將本地地址綁定到監(jiān)聽(tīng)套接字*/if ( bind( listenfd, (struct sockaddr *)& servaddr, sizeof(servaddr) 0) fprintf(stderr, ”bind failedn” );exit(1); /* 開(kāi)始監(jiān)聽(tīng),并指定監(jiān)聽(tīng)套接字請(qǐng)求隊(duì)列的長(zhǎng)度開(kāi)始監(jiān)聽(tīng),并指定監(jiān)聽(tīng)套接字請(qǐng)求隊(duì)列的長(zhǎng)度 */if (listen(listenfd, QLEN) 0) fprintf(stderr, ”listen filedn” );exit(1);
60、/* 服務(wù)器主循環(huán)服務(wù)器主循環(huán)接受和處理來(lái)自客戶端的連接請(qǐng)求接受和處理來(lái)自客戶端的連接請(qǐng)求 */while(1) alen = sizeof(clientaddr); /* 接受客戶端連接請(qǐng)求,并生成響應(yīng)套接字接受客戶端連接請(qǐng)求,并生成響應(yīng)套接字 */ if(clientfd = accept( listenfd, (struct sockaddr *)& clientaddr, &alen) 0 ) fprintf( stderr, “accept failedn”); exit(1); visits+; /* 累加訪問(wèn)的客戶數(shù)累加訪問(wèn)的客戶數(shù) */ sprintf( buf, “this server has been contacted %d time n”, visits ); se
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2023年-2024年公司項(xiàng)目部負(fù)責(zé)人安全教育培訓(xùn)試題附答案【黃金題型】
- 立秋文化在新媒體的傳播
- 《材料工程原理緒論》課件
- 《監(jiān)督培訓(xùn)材料》課件
- 激光打標(biāo)機(jī)打標(biāo)軟件與PLC通信穩(wěn)定性的研究
- 部編版七年級(jí)歷史下冊(cè)期末復(fù)習(xí)專題課件2024版
- 云安全隱私保護(hù)機(jī)制-洞察分析
- 營(yíng)養(yǎng)產(chǎn)業(yè)可持續(xù)發(fā)展-洞察分析
- 外觀模式可維護(hù)性-洞察分析
- 稀有金屬國(guó)際市場(chǎng)動(dòng)態(tài)-洞察分析
- 2024-2029年中國(guó)IP授權(quán)行業(yè)市場(chǎng)現(xiàn)狀分析及競(jìng)爭(zhēng)格局與投資發(fā)展研究報(bào)告
- 北京市海淀區(qū)2023-2024學(xué)年四年級(jí)上學(xué)期期末英語(yǔ)試題
- 2024年湖北省漢江國(guó)有資本投資集團(tuán)有限公司招聘筆試參考題庫(kù)含答案解析
- 廣州市九區(qū)聯(lián)考2023-2024學(xué)年高一上學(xué)期期末教學(xué)質(zhì)量監(jiān)測(cè)數(shù)學(xué)試卷(原卷版)
- 西方國(guó)家的量刑建議制度及其比較
- 游戲方案模板
- 幼兒園大班數(shù)學(xué)上學(xué)期期末考試-試題測(cè)試
- 地震預(yù)警安裝方案
- 汽車產(chǎn)品定義 培訓(xùn)課件
- NICU患兒常規(guī)監(jiān)測(cè)和護(hù)理要點(diǎn)
- 數(shù)字工程勘察信息平臺(tái)構(gòu)建
評(píng)論
0/150
提交評(píng)論