蔡坤琪,趙安學(xué),邢潔清*
(1.瓊臺(tái)師范學(xué)院 信息科學(xué)技術(shù)學(xué)院,海南 海口 571100;2.瓊臺(tái)師范學(xué)院 教育大數(shù)據(jù)與人工智能研究所,海南 ???571100)
在計(jì)算機(jī)網(wǎng)絡(luò)中,網(wǎng)絡(luò)主機(jī)除了要給本地用戶提供服務(wù),還要給網(wǎng)絡(luò)的其他主機(jī)的用戶提供服務(wù)。為遠(yuǎn)程計(jì)算機(jī)提供服務(wù)的進(jìn)程被稱為Server進(jìn)程,本地計(jì)算機(jī)請(qǐng)求服務(wù)并發(fā)起本次進(jìn)程通信的進(jìn)程被稱為Client進(jìn)程。當(dāng)客戶端進(jìn)程發(fā)出服務(wù)請(qǐng)求時(shí),遠(yuǎn)程服務(wù)器進(jìn)程會(huì)響應(yīng)該客戶端請(qǐng)求,并提供進(jìn)程間通信的一種模式,被稱為客戶端/服務(wù)器模式。
在TCP/IP網(wǎng)絡(luò)應(yīng)用中,通信的兩個(gè)進(jìn)程間相互作用的主要模式是客戶機(jī)/服務(wù)器模式(Client/Server),采用Client/ Server模式的理由主要有以下幾點(diǎn)。
互聯(lián)網(wǎng)資源分布具有不均勻性。
2.1.1 硬件
網(wǎng)絡(luò)中主機(jī)系統(tǒng)類型的作用和能力等各方面差異很大。主機(jī)設(shè)備可以是某臺(tái)大型的電腦高配置的服務(wù)器,也可以是一臺(tái)個(gè)人電腦,甚至是一個(gè)PDA或是一個(gè)家電。
2.1.2 軟件
由于所屬權(quán)管理與運(yùn)行環(huán)境等方面的原因,應(yīng)用軟件都是安裝在客戶端主機(jī)系統(tǒng)中,用戶可以訪問(wèn)網(wǎng)絡(luò),注冊(cè)成合法用戶,然后提出和完成計(jì)算任務(wù)。
在互聯(lián)網(wǎng)環(huán)境中,進(jìn)程通信具有異步性。不同結(jié)點(diǎn)分布在不同網(wǎng)絡(luò)空間,結(jié)點(diǎn)系統(tǒng)中的進(jìn)程不時(shí)發(fā)出通信請(qǐng)求,希望和某臺(tái)主機(jī)的某個(gè)進(jìn)程通信。
該模式不存在統(tǒng)一調(diào)度與協(xié)調(diào)的高層操作系統(tǒng)。
Client/ Server模式的工作實(shí)質(zhì)是“請(qǐng)求驅(qū)動(dòng)”。毎次通信由Client進(jìn)程隨機(jī)發(fā)起。
在互聯(lián)網(wǎng)中,Server必須要有處理并發(fā)請(qǐng)求的能力。在同一個(gè)時(shí)點(diǎn),可能有多個(gè)Client進(jìn)程向一個(gè)Server發(fā)出服務(wù)請(qǐng)求。
解決服務(wù)器處理并發(fā)請(qǐng)求的方案基本上有以下兩種:一是采用并發(fā)服務(wù)器的方法;二是采用重復(fù)服務(wù)器的方法。
服務(wù)器并發(fā)的核心是服務(wù)器的守護(hù)程序(Daemon),系統(tǒng)啟動(dòng)的時(shí)候隨之啟動(dòng)。在沒(méi)有Client的服務(wù)請(qǐng)求到達(dá)時(shí),并發(fā)Server處于等待狀態(tài)。
當(dāng)客戶端服務(wù)請(qǐng)求到達(dá)時(shí),服務(wù)器端根據(jù)客戶端的服務(wù)請(qǐng)求的進(jìn)程激活相應(yīng)的子進(jìn)程,該子進(jìn)程為客戶端提供服務(wù),服務(wù)器返回等待狀態(tài)。
服務(wù)器必須具有在整個(gè)網(wǎng)絡(luò)中眾所周知的進(jìn)程地址?;ヂ?lián)網(wǎng)中的Client進(jìn)程可以根據(jù)Server進(jìn)程的熟知地址,向Server提出服務(wù)請(qǐng)求。在實(shí)現(xiàn)進(jìn)程通信的過(guò)程中,Client與 Server進(jìn)程分別形成自己的半相關(guān)的三元組,然后Client根據(jù)Server進(jìn)程的熟知進(jìn)程地址建立相關(guān)的五元組。
重復(fù)服務(wù)器通過(guò)設(shè)置請(qǐng)求隊(duì)列來(lái)存儲(chǔ)客戶端的服務(wù)請(qǐng)求。服務(wù)器采用先到先得的原則,依次處理客戶的服務(wù)請(qǐng)求。
并發(fā) Server適應(yīng)于面向連接的服務(wù)類型,而重復(fù) Server適應(yīng)于無(wú)連接的服務(wù)類型。
BSD UNIX更直觀地解釋網(wǎng)絡(luò)環(huán)境中進(jìn)程通信的實(shí)現(xiàn)方法。
3.2.1 socket的基本概念
套接字是中間件抽象層,用于在應(yīng)用程序?qū)雍蚑CP/IP協(xié)議套件之間的通信。它是一組接口。socket將復(fù)雜的TCP/IP協(xié)議系列隱藏在socket接口后面。用戶擁有了一套簡(jiǎn)單的接口,從而使socket可以組織數(shù)據(jù),遵守指定的協(xié)議。
3.2.2 套接字通信機(jī)制
套接字允許位于不同計(jì)算機(jī)上的互聯(lián)進(jìn)程執(zhí)行通信功能。使用套接字可在特定計(jì)算機(jī)上標(biāo)記和定位特定進(jìn)程的地址,以便可以將數(shù)據(jù)準(zhǔn)確地傳輸?shù)侥繕?biāo)進(jìn)程。套接字包含3個(gè)參數(shù):通信目標(biāo)IP地址、傳輸層協(xié)議(TCP或UDP)和端口號(hào)。IP地址用于標(biāo)識(shí)目標(biāo)計(jì)算機(jī),端口號(hào)用于標(biāo)識(shí)目標(biāo)計(jì)算機(jī)上的特定進(jìn)程。套接字之間的連接分為3個(gè)階段:監(jiān)視服務(wù)器、請(qǐng)求客戶端和確認(rèn)連接[2]。
對(duì)于UNIX系統(tǒng),socket調(diào)用是網(wǎng)絡(luò)的輸入/輸出。
3.3.1 創(chuàng)建socket—socket()
應(yīng)用程序在使用socket之前必須首先擁有一個(gè)socket號(hào)。這就相當(dāng)于用戶在安裝電話時(shí)首先要向電話局申請(qǐng)一個(gè)電話號(hào)碼。
socket()向應(yīng)用程序提供創(chuàng)建socket的手段,socket()調(diào)用的格式是:
Socketid=socket (af, type, protocol)
返回的Socketid值是一個(gè)整數(shù),申請(qǐng)一個(gè)屬于自己此次進(jìn)程通信的socket號(hào),創(chuàng)建socket,實(shí)際上是申請(qǐng)1個(gè)屬于自己此次進(jìn)程通信的socket號(hào),socket()一共有以下3個(gè)參數(shù):①地址族(address family af);②類型type;③協(xié)議protocol。它們分別代表socket使用的地址類型,創(chuàng)建socket的應(yīng)用程序所希望的通信服務(wù)類型以及socket請(qǐng)求使用的協(xié)議。
3.3.2 指定本地地址—bind()
創(chuàng)建socket()并且調(diào)用,是完成socket通信創(chuàng)建的第一步。它僅在相關(guān)的五元組中指定協(xié)議,并且bind()系統(tǒng)調(diào)用會(huì)給出本地地址和本地端口。
bind()系統(tǒng)調(diào)用的格式是:bind(socketid,localaddr,addr elen)
其中,Socketid是本地的socket號(hào);localaddr是本地地址,在TCP/IP族中它就是本地主機(jī)的IP地址;addrelen對(duì)應(yīng)于IP地址長(zhǎng)度。
3.3.3 建立套接字連接connect()和accept()
accept()和connect()調(diào)用終止兩個(gè)關(guān)聯(lián)的連接。其中,connect()用于建立連接。連接在這里有兩種含義,一種是在兩個(gè)socket之間進(jìn)行通信,另一種是在傳輸層建立連接。例如,TCP的connect()連接調(diào)用主要用于面向連接的傳輸服務(wù),而accept()調(diào)用用于面向連接的傳輸服務(wù)。無(wú)連接socket進(jìn)程可以調(diào)用connect()。但是,此時(shí)本地系統(tǒng)和遠(yuǎn)程系統(tǒng)之間沒(méi)有真正的連接,它實(shí)際上通知操作系統(tǒng),它將指定的套接字?jǐn)?shù)據(jù)發(fā)送到此套接字。
3.3.4 接收socket連接—listen()
listen()調(diào)用是用于面向連接Server,它表示同意接受連接。
listen()調(diào)用格式是:listen(socketid,quelen)
其中,Socketid是本地socket號(hào),表示Server可以在此socket號(hào)上接受服務(wù)請(qǐng)求,quelen表示請(qǐng)求的隊(duì)列長(zhǎng)度。
3.3.5 發(fā)送數(shù)據(jù)write()writev()與send()sendto()sendmsg()
用于面向連接傳輸write()writev()send()調(diào)用的格式比較一致,例如:
緩沖發(fā)送:write(socketid,buffbuffon)
集中發(fā)送:writev(socketid,iovecor,vectorlen)
可控緩沖發(fā)送:send(socketid,buff,buffer,flags)
3.3.6 接收數(shù)據(jù)read()readv()與recvfrom()recvmsg()
接收數(shù)據(jù)調(diào)用read()ready()與recvfrom()recvmsg()和發(fā)送數(shù)據(jù)調(diào)用是對(duì)應(yīng)的。不同之處在于,發(fā)送數(shù)據(jù)調(diào)用的Buff是指針,而接收數(shù)據(jù)調(diào)用中的Buff是實(shí)際讀出的值。
Client/Server模式直至今天仍然有其自身的優(yōu)勢(shì),這種應(yīng)用程序體系結(jié)構(gòu)仍將長(zhǎng)期存在。學(xué)習(xí)和了解這種模式,有助于人們理解Client/Server模式,對(duì)基于這種模式的應(yīng)用程序開(kāi)發(fā)和服務(wù)的搭建都很有益處。