本章以Berkeley Socket為主,主要介紹網(wǎng)絡(luò)編程時常用的調(diào)用和程序使用它們的方法及基本結(jié)構(gòu)。網(wǎng)絡(luò)編程有兩種主要的編程接口,一種是Berkeley UNIX(BSD UNIX)的socket編程接口,另一種是AT&T的TLI接口(用于UNIXSYSV)。
1 、TCP/IP 基礎(chǔ)知識
這里先假定讀者對ISO的OSI七層模型已有了一定的了解,下面我們來看看TCP/IP模型。ISO的OSI對服務(wù)、接口和協(xié)議的概念區(qū)別十分明了,但它卻沒有真正的用戶群。TCP/IP模型對服務(wù)、接口和協(xié)議的概念區(qū)別不象OSI模型那樣明晰,但很實用。TCP/IP模型分為四層,對應(yīng)于OSI七層模型如下圖所示:圖6-1 TCP/IP參考模型與OSI模型的近似對應(yīng)關(guān)系在TCP/IP模型中,互聯(lián)網(wǎng)層是基于無連接互聯(lián)網(wǎng)絡(luò)層的分組交換網(wǎng)絡(luò)。在這一層中主機可以把報文(Packet)發(fā)往任何網(wǎng)絡(luò),報文獨立地傳向目標(biāo)?;ヂ?lián)網(wǎng)層定義了報文的格式和協(xié)議,這就是IP協(xié)議族(Internet Protocol)?;ヂ?lián)網(wǎng)層的功能是將報文發(fā)送到目的地,主要的設(shè)計問題是報文路由和避免阻塞。互聯(lián)網(wǎng)層上面是傳輸層,該層的主要功能和OSI模型的該層一樣,主要使源和目的主機之間可以進行會話。該層定義了兩個端到端的協(xié)議,一個是面向連接的傳輸控制協(xié)議TCP,另一個是無連接的用戶數(shù)據(jù)報協(xié)議UDP。TCP/IP協(xié)議模型中沒有會話層和表示層。傳輸層之上是應(yīng)用層,它包含所有的高層協(xié)議,如遠(yuǎn)程虛擬終端協(xié)議TELNET、文件傳輸協(xié)議FTP、簡單郵件傳輸協(xié)議SMTP等。這些高層協(xié)議中常見的如TELNET協(xié)議,用來允許用戶遠(yuǎn)程登錄到另一臺UNIX機器;FTP協(xié)議用來傳輸文件,常見的有WU-FTP(Washington University的FTP服務(wù)器端程序,是一個免費程序);SMTP協(xié)議用來傳送email,常見的服務(wù)器端程序有netscape等公司制作的程序,也有免費使用的sendmail程序;還有域名系統(tǒng)服務(wù)DNS協(xié)議,新聞組傳送協(xié)議NNTP,用于WWW的超文本傳輸協(xié)議HTTP等。主機到網(wǎng)絡(luò)這一層,在TCP/IP模型中沒有詳細(xì)定義,這里不作介紹。
2、 Socket一般描述
由于越來越多的計算機廠商,特別是工作站制造商如Sun等公司采用了Berkeley UNIX,socket接口被廣泛采用,以至于現(xiàn)在,socket接口被廣泛認(rèn)可并成為了事實上的工業(yè)標(biāo)準(zhǔn)。目前的SYSV、BSD、OSF都將socket接口作為系統(tǒng)的一部分。當(dāng)時設(shè)計如何支持TCP/IP協(xié)議時,有兩種加入函數(shù)的方法,一種是直接加入支持TCP/IP協(xié)議的調(diào)用,另一種是加入支持一般網(wǎng)絡(luò)協(xié)議的函數(shù),而用參數(shù)來指定支持TCP/IP協(xié)議。Berkeley采用了后者,這樣可以支持多協(xié)議族,TCP/IP是協(xié)議族之一(PF_INET)。
2.1 socket 描述符
前面已經(jīng)提到過,在UNIX中,進程要對文件進行操作,一般使用open調(diào)用打開一個文件進行訪問,每個進程都有一個文件描述符表,該表中存放打開的文件描述符。用戶使用open等調(diào)用得到的文件描述符其實是文件描述符在該表中的索引號,該表項的內(nèi)容是一個指向文件表的指針。應(yīng)用程序只要使用該描述符就可以對指定文件進行操作。同樣,socket接口增加了網(wǎng)絡(luò)通信操作的抽象定義,與文件操作一樣,每個打開的socket都對應(yīng)一個整數(shù),我們稱它為socket描述符,該整數(shù)也是socket描述符在文件描述符表中的索引值。但socket描述符在描述符表中的表項并不指向文件表,而是指向一個與該socket有關(guān)的數(shù)據(jù)結(jié)構(gòu)。BSD UNIX中新增加了一個socket調(diào)用,應(yīng)用程序可以調(diào)用它來新建一個socket描述符,注意進程用open只能產(chǎn)生文件描述符,而不能產(chǎn)生socket描述符。socket調(diào)用只能完成建立通信的部分工作,一旦建立了一個socket,應(yīng)用程序可以使用其他特定的調(diào)用來為它添加其他詳細(xì)信息,以完成建立通信的過程。
2.2 從概念上理解socket的使用網(wǎng)絡(luò)編程中最常見的是客戶/服務(wù)器模式。
以該模式編程時,服務(wù)端有一個進程(或多個進程)在指定的端口等待客戶來連接,服務(wù)程序等待客戶的連接信息,一旦連接上之后,就可以按設(shè)計的數(shù)據(jù)交換方法和格式進行數(shù)據(jù)傳輸??蛻舳嗽谛枰臅r刻發(fā)出向服務(wù)端的連接請求。
這里為了便于理解,提到了這些調(diào)用及其大致的功能。使用socket調(diào)用后,僅產(chǎn)生了一個可以使用的socket描述符,這時還不能進行通信,還要使用其他的調(diào)用,以使得socket所指的結(jié)構(gòu)中使用的信息被填寫完。在使用TCP協(xié)議時,一般服務(wù)端進程先使用socket調(diào)用得到一個描述符,然后使用bind調(diào)用將一個名字與socket描述符連接起來,對于Internet域就是將Internet地址聯(lián)編到socket。之后,服務(wù)端使用listen調(diào)用指出等待服務(wù)請求隊列的長度。然后就可以使用accept調(diào)用等待客戶端發(fā)起連接(一般是阻塞等待連接,后面章節(jié)會講到非阻塞的方式),一旦有客戶端發(fā)出連接,accept返回客戶的地址信息,并返回一個新的socket描述符,該描述符與原先的socket有相同的特性,這時服務(wù)端就可以使用這個新的socket進行讀寫操作了。一般服務(wù)端可能在accept返回后創(chuàng)建一個新的進程進行與客戶的通信,父進程則再到accept調(diào)用處等待另一個連接??蛻舳诉M程一般先使用socket調(diào)用得到一個socket描述符,然后使用connect向指定的服務(wù)器上的指定端口發(fā)起連接,一旦連接成功返回,就說明已經(jīng)建立了與服務(wù)器的連接,這時就可以通過socket描述符進行讀寫操作了。下面是在客戶和服務(wù)端使用TCP時,客戶進程和服務(wù)進程使用系統(tǒng)調(diào)用的該程。
使用TCP的客戶和服務(wù)端使用系統(tǒng)調(diào)用的圖示使用無連接的UDP協(xié)議時,服務(wù)端進程創(chuàng)建一個socket,之后調(diào)用recvfrom接收客戶端的數(shù)據(jù)報,然后調(diào)用sendto將要返回客戶端的消息發(fā)送給客戶進程??蛻舳艘惨葎?chuàng)建一個socket,再使用sendto向服務(wù)端進程發(fā)出請求,使用recvfrom得到返回的消息。
聯(lián)系客服