Python程序開(kāi)發(fā)案例教程(第2版)課件 第13章 網(wǎng)絡(luò)編程_第1頁(yè)
Python程序開(kāi)發(fā)案例教程(第2版)課件 第13章 網(wǎng)絡(luò)編程_第2頁(yè)
Python程序開(kāi)發(fā)案例教程(第2版)課件 第13章 網(wǎng)絡(luò)編程_第3頁(yè)
Python程序開(kāi)發(fā)案例教程(第2版)課件 第13章 網(wǎng)絡(luò)編程_第4頁(yè)
Python程序開(kāi)發(fā)案例教程(第2版)課件 第13章 網(wǎng)絡(luò)編程_第5頁(yè)
已閱讀5頁(yè),還剩92頁(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)介

第13章網(wǎng)絡(luò)編程《Python程序開(kāi)發(fā)案例教程(第2版))》學(xué)習(xí)目標(biāo)/Target

了解協(xié)議與體系結(jié)構(gòu),能夠說(shuō)出五層協(xié)議體系結(jié)構(gòu)中各層的功能,區(qū)分TCP協(xié)議和UDP協(xié)議的特點(diǎn)了解數(shù)據(jù)傳輸流程,能夠說(shuō)出兩個(gè)進(jìn)程通信的數(shù)據(jù)傳輸流程了解網(wǎng)絡(luò)架構(gòu),能夠說(shuō)出C/S架構(gòu)和B/S架構(gòu)的特點(diǎn)了解IP地址和端口號(hào),能夠說(shuō)出它們的作用及特點(diǎn)掌握socket套接字的創(chuàng)建方式,能夠通過(guò)socket()方法創(chuàng)建基于TCP通信的流式套接字學(xué)習(xí)目標(biāo)/Target

熟悉socket通信流程,能夠歸納面向連接通信和面向非連接通信的流程

掌握socket內(nèi)置方法,能夠通過(guò)這些方法實(shí)現(xiàn)socket通信掌握基于UDP的網(wǎng)絡(luò)聊天室功能,能夠?qū)崿F(xiàn)基于UDP的網(wǎng)絡(luò)聊天室掌握基于TCP的數(shù)據(jù)轉(zhuǎn)換功能,能夠?qū)崿F(xiàn)基于TCP的數(shù)據(jù)轉(zhuǎn)換

掌握并發(fā)服務(wù)器,能夠?qū)崿F(xiàn)單進(jìn)程非阻塞服務(wù)器、多進(jìn)程并發(fā)服務(wù)器以及多線程并發(fā)服務(wù)器章節(jié)概述/Summary隨著計(jì)算機(jī)與互聯(lián)網(wǎng)的普及和發(fā)展,網(wǎng)絡(luò)已經(jīng)廣泛滲透到社會(huì)生活的各個(gè)方面,無(wú)論是操作系統(tǒng)還是手機(jī)應(yīng)用,都與網(wǎng)絡(luò)密切相關(guān)。網(wǎng)絡(luò)編程是Python學(xué)習(xí)中的一個(gè)關(guān)鍵環(huán)節(jié),它能夠幫助讀者理解網(wǎng)絡(luò)通信的工作原理,實(shí)現(xiàn)高效的數(shù)據(jù)交換,掌握構(gòu)建高效可靠的網(wǎng)絡(luò)應(yīng)用程序的技能。本章將對(duì)Python中網(wǎng)絡(luò)編程的相關(guān)知識(shí)進(jìn)行講解。目錄/Contents010203網(wǎng)絡(luò)概述socket網(wǎng)絡(luò)編程基礎(chǔ)基于UDP的網(wǎng)絡(luò)聊天室目錄/Contents040506基于TCP的數(shù)據(jù)轉(zhuǎn)換實(shí)例2:TCP文件下載TCP并發(fā)服務(wù)器網(wǎng)絡(luò)概述13.1

先定一個(gè)小目標(biāo)!了解協(xié)議與體系結(jié)構(gòu),能夠說(shuō)出五層協(xié)議體系結(jié)構(gòu)中各層的功能,區(qū)分TCP協(xié)議和UDP協(xié)議的特點(diǎn)13.1.1協(xié)議與體系結(jié)構(gòu)協(xié)議網(wǎng)絡(luò)中存在多臺(tái)主機(jī),為保證主機(jī)間能順利通訊,且通信雙方可以獲取到準(zhǔn)確、有效的數(shù)據(jù),應(yīng)制訂一組用于數(shù)據(jù)傳輸?shù)囊?guī)則,這組規(guī)則就是協(xié)議。13.1.1協(xié)議與體系結(jié)構(gòu)1.網(wǎng)絡(luò)體系結(jié)構(gòu)計(jì)算機(jī)網(wǎng)絡(luò)中常見(jiàn)的體系結(jié)構(gòu)有OSI(開(kāi)放式系統(tǒng)互聯(lián)模型)和TCP/IP(傳輸控制協(xié)議/互聯(lián)網(wǎng)協(xié)議模型)。OSI由國(guó)際標(biāo)準(zhǔn)協(xié)會(huì)ISO制定,共分為七層,由上而下依次為應(yīng)用層、表示層、會(huì)話層、傳輸層、網(wǎng)絡(luò)層、數(shù)據(jù)鏈路層和物理層,雖然OSI由ISO制定,但其實(shí)用性較差,并未得到廣泛應(yīng)用。13.1.1協(xié)議與體系結(jié)構(gòu)1.網(wǎng)絡(luò)體系結(jié)構(gòu)在OSI誕生時(shí),因特網(wǎng)已實(shí)現(xiàn)了全世界的基本覆蓋,因此市面上應(yīng)用最廣泛的體系結(jié)構(gòu)為因特網(wǎng)中使用的TCP/IP體系結(jié)構(gòu),該結(jié)構(gòu)包含四層,分別為應(yīng)用層、傳輸層、網(wǎng)際層和網(wǎng)絡(luò)接口層。13.1.1協(xié)議與體系結(jié)構(gòu)1.網(wǎng)絡(luò)體系結(jié)構(gòu)13.1.1協(xié)議與體系結(jié)構(gòu)在計(jì)算機(jī)網(wǎng)絡(luò)中通常以一種包含五層協(xié)議的體系結(jié)構(gòu)來(lái)講解各層之間的功能與聯(lián)系,這種體系結(jié)構(gòu)結(jié)合OSI和TCP/IP的優(yōu)點(diǎn),分為應(yīng)用層、傳輸層、網(wǎng)絡(luò)層、數(shù)據(jù)鏈路層和物理層。物理層:計(jì)算機(jī)體系結(jié)構(gòu)的最底層,它為設(shè)備之間的數(shù)據(jù)傳輸提供可靠的環(huán)境。數(shù)據(jù)鏈路層:簡(jiǎn)稱鏈路層,它將從網(wǎng)絡(luò)層獲取的數(shù)據(jù)報(bào)組裝成幀,在網(wǎng)絡(luò)結(jié)點(diǎn)之間以幀為單位傳輸數(shù)據(jù)。網(wǎng)絡(luò)層:為分組交換網(wǎng)上的不同主機(jī)提供通信服務(wù)。在進(jìn)行通信時(shí),網(wǎng)絡(luò)層會(huì)將從傳輸層獲取的報(bào)文段或數(shù)據(jù)報(bào)進(jìn)行封裝,形成分組或包。這些數(shù)據(jù)或包通常被稱為數(shù)據(jù)報(bào)。傳輸層:為應(yīng)用進(jìn)程提供連接服務(wù),實(shí)現(xiàn)連接兩端進(jìn)程的會(huì)話。應(yīng)用層:為應(yīng)用進(jìn)程提供服務(wù),定義了應(yīng)用進(jìn)程間通信和交互的規(guī)則。1.網(wǎng)絡(luò)體系結(jié)構(gòu)13.1.1協(xié)議與體系結(jié)構(gòu)OSI、TCP/IP和五層協(xié)議體系結(jié)構(gòu)各層對(duì)應(yīng)關(guān)系。13.1.1協(xié)議與體系結(jié)構(gòu)2.協(xié)議計(jì)算機(jī)網(wǎng)絡(luò)通信基于TCP/IP,TCP/IP實(shí)際上是協(xié)議族,它由多種協(xié)議構(gòu)成,包括TCP協(xié)議、UDP協(xié)議、IP協(xié)議等等,其中TCP、UDP協(xié)議應(yīng)用在傳輸層;IP協(xié)議應(yīng)用在網(wǎng)絡(luò)層。TCP協(xié)議即傳輸控制協(xié)議(TransmissionControlProtocol),該協(xié)議是一種面向連接的、可靠的、基于字節(jié)流的傳輸協(xié)議。在傳遞數(shù)據(jù)之前,收發(fā)雙方會(huì)先通過(guò)一種被稱為“三次握手”的協(xié)商機(jī)制建立連接,為數(shù)據(jù)傳輸做好準(zhǔn)備。為了防止報(bào)文段丟失,TCP會(huì)給每個(gè)數(shù)據(jù)段一個(gè)序號(hào),使接收端按序號(hào)順序接收數(shù)據(jù)。若接收端正常接收到報(bào)文段,向發(fā)送端發(fā)送一個(gè)確認(rèn)信息;若發(fā)送端在一定的時(shí)延后未接收到確認(rèn)信息,便假設(shè)報(bào)文段已丟失,并重新向接收端發(fā)送對(duì)應(yīng)報(bào)文段。此外,TCP協(xié)議中定義了一個(gè)校驗(yàn)函數(shù),用于檢測(cè)發(fā)送和接收的數(shù)據(jù),防止產(chǎn)生數(shù)據(jù)錯(cuò)誤。13.1.1協(xié)議與體系結(jié)構(gòu)TCP協(xié)議13.1.1協(xié)議與體系結(jié)構(gòu)TCP協(xié)議通信結(jié)束后,通信雙方經(jīng)過(guò)“四次握手”關(guān)閉連接。因?yàn)門CP連接是全雙工的,全雙工是指交換機(jī)在發(fā)送數(shù)據(jù)的同時(shí)也能夠接收數(shù)據(jù),兩者同步進(jìn)行,類似語(yǔ)音通話,雙方在說(shuō)話的同時(shí)也能夠聽(tīng)到對(duì)方的聲音,所以每個(gè)方向必須單獨(dú)關(guān)閉連接,即連接的一端需先發(fā)送關(guān)閉信息到另一端,當(dāng)關(guān)閉信息發(fā)送后,發(fā)送關(guān)閉信息的一端不會(huì)再發(fā)送信息,但另一端仍可向該端發(fā)送信息。13.1.1協(xié)議與體系結(jié)構(gòu)UDP協(xié)議UDP協(xié)議即用戶數(shù)據(jù)報(bào)協(xié)議,它是一種無(wú)連接的傳輸層協(xié)議。UDP的收發(fā)雙方?jīng)]有建立連接,當(dāng)按照UDP協(xié)議傳輸數(shù)據(jù)時(shí),發(fā)送方使用套接字文件發(fā)送數(shù)據(jù)報(bào)給接收方,之后可立即使用同一個(gè)套接字發(fā)送其他數(shù)據(jù)報(bào)給另一個(gè)接收方;同樣的,接收方也可以通過(guò)相同的套接字接收由多個(gè)發(fā)送方發(fā)來(lái)的數(shù)據(jù)。13.1.1協(xié)議與體系結(jié)構(gòu)UDP協(xié)議UDP不對(duì)數(shù)據(jù)報(bào)進(jìn)行編號(hào),它不保證接收方以正確的順序接收到完整的數(shù)據(jù),但會(huì)將數(shù)據(jù)報(bào)的長(zhǎng)度隨數(shù)據(jù)發(fā)送給接收方。雖然UDP面向無(wú)連接的通信,不能如TCP般很好地保證數(shù)據(jù)的完整性和正確性,但UDP處理速度快,耗費(fèi)資源少,因此在對(duì)數(shù)據(jù)完整性要求低、對(duì)傳輸效率要求高的應(yīng)用中一般使用UDP協(xié)議傳輸數(shù)據(jù)。13.1.1協(xié)議與體系結(jié)構(gòu)IP協(xié)議IP協(xié)議的兩個(gè)基本功能為尋址和分段。傳輸層的數(shù)據(jù)封裝完成后沒(méi)有直接發(fā)送到接收方,而是先遞達(dá)網(wǎng)絡(luò)層;網(wǎng)絡(luò)層又在原數(shù)據(jù)報(bào)前添加IP首部,封裝成IP數(shù)據(jù)報(bào),并解析數(shù)據(jù)報(bào)中的目的地址,為其選擇傳輸路徑,將數(shù)據(jù)報(bào)發(fā)送到接收方。IP協(xié)議中這種選擇傳輸路徑的功能稱為路由功能。此外,IP協(xié)議可重新組裝數(shù)據(jù)報(bào),改變數(shù)據(jù)報(bào)的大小,以適應(yīng)不同網(wǎng)絡(luò)對(duì)數(shù)據(jù)包大小的要求。需要說(shuō)明的是,IP協(xié)議不提供端到端或結(jié)點(diǎn)到結(jié)點(diǎn)的確認(rèn),只檢測(cè)報(bào)頭中的校驗(yàn)碼,不提供可靠的傳輸服務(wù)。13.1.1協(xié)議與體系結(jié)構(gòu)IP協(xié)議雖然各層使用的協(xié)議互不相同,但協(xié)議通常都由以下3個(gè)部分組成:①待交互數(shù)據(jù)的結(jié)構(gòu)和格式;②進(jìn)行交互的方式,包括數(shù)據(jù)的類型、對(duì)數(shù)據(jù)的處理動(dòng)作等;③事件實(shí)現(xiàn)順序的說(shuō)明。一組完整的協(xié)議不僅需要考慮通信雙方在正常情況下的動(dòng)作,還應(yīng)考慮到通信時(shí)可能出現(xiàn)的異常,并對(duì)異常情況下通信雙方的動(dòng)作做出規(guī)定。

先定一個(gè)小目標(biāo)!了解數(shù)據(jù)傳輸流程,能夠說(shuō)出兩個(gè)進(jìn)程通信的數(shù)據(jù)傳輸流程13.1.2數(shù)據(jù)傳輸流程數(shù)據(jù)傳輸流程13.1.2數(shù)據(jù)傳輸流程數(shù)據(jù)傳輸流程13.1.2數(shù)據(jù)傳輸流程數(shù)據(jù)傳輸流程兩個(gè)進(jìn)程進(jìn)行通信時(shí),數(shù)據(jù)傳輸流程以及數(shù)據(jù)的變化情況如下:(1)來(lái)自一個(gè)進(jìn)程的數(shù)據(jù)遞達(dá)應(yīng)用層,應(yīng)用層根據(jù)本層協(xié)議在數(shù)據(jù)的頭部添加相應(yīng)控制信息h5,之后將數(shù)據(jù)傳向傳輸層。(2)傳輸層接收來(lái)自應(yīng)用層的信息,并通過(guò)TCP協(xié)議或UDP協(xié)議添加控制信息h4(TCP首部或UDP首部),添加完成后作為數(shù)據(jù)段或數(shù)據(jù)包傳向網(wǎng)絡(luò)層。(3)網(wǎng)絡(luò)層接收來(lái)自傳輸層的數(shù)據(jù)段或數(shù)據(jù)包,為其添加控制信息h3(IP首部)并封裝為IP數(shù)據(jù)報(bào),傳遞到數(shù)據(jù)鏈路層。13.1.2數(shù)據(jù)傳輸流程數(shù)據(jù)傳輸流程兩個(gè)進(jìn)程進(jìn)行通信時(shí),數(shù)據(jù)傳輸流程以及數(shù)據(jù)的變化情況如下:(4)數(shù)據(jù)鏈路層接收到來(lái)自網(wǎng)絡(luò)層的IP數(shù)據(jù)報(bào),在IP數(shù)據(jù)報(bào)的頭部和尾部分別添加控制信息h2,封裝成數(shù)據(jù)幀并傳遞到物理層。(5)物理層接收到來(lái)自數(shù)據(jù)鏈路層的數(shù)據(jù)幀,將其轉(zhuǎn)化為由0、1代碼組成的比特流,再傳送到物理傳輸媒介。(6)物理傳輸媒介中的比特流經(jīng)路由轉(zhuǎn)發(fā),首先遞達(dá)另一個(gè)進(jìn)程所在的物理傳輸媒介中,然后按照TCP/IP協(xié)議族中的協(xié)議,將比特流格式的數(shù)據(jù)轉(zhuǎn)換為數(shù)據(jù)幀,依次去除數(shù)據(jù)鏈路層、網(wǎng)絡(luò)層、傳輸層和應(yīng)用層添加的控制信息,最后將原始數(shù)據(jù)傳送給另一個(gè)進(jìn)程。體系結(jié)構(gòu)中各層的實(shí)現(xiàn)建立在其下一層所提供的服務(wù)上,且本層繼續(xù)向上層提供服務(wù),各層之間的常用協(xié)議以及層級(jí)關(guān)系如圖所示。13.1.2數(shù)據(jù)傳輸流程數(shù)據(jù)傳輸流程

先定一個(gè)小目標(biāo)!了解網(wǎng)絡(luò)架構(gòu),能夠說(shuō)出C/S架構(gòu)和B/S架構(gòu)的特點(diǎn)13.1.3網(wǎng)絡(luò)架構(gòu)網(wǎng)絡(luò)架構(gòu)13.1.3網(wǎng)絡(luò)架構(gòu)網(wǎng)絡(luò)架構(gòu)分為C/S架構(gòu)和B/S架構(gòu),其中C/S架構(gòu)即客戶機(jī)(Client)/服務(wù)器(Server)模式,這種架構(gòu)需要在進(jìn)行通信的兩端分別架設(shè)客戶機(jī)和服務(wù)器,常見(jiàn)的基于C/S架構(gòu)的有銀行系統(tǒng)中的ATM機(jī)、打印店中的電腦與打印機(jī)等;B/S架構(gòu)是瀏覽器(Browser)/服務(wù)器(Server)架構(gòu),這是WEB(WorldWideWeb,萬(wàn)維網(wǎng))興起后的一種網(wǎng)絡(luò)架構(gòu),客戶機(jī)只需安裝瀏覽器,便可與服務(wù)器進(jìn)行交互,常見(jiàn)的B/S架構(gòu)如百度、谷歌等瀏覽器建設(shè)、大多學(xué)校使用的校園網(wǎng),以及公司內(nèi)網(wǎng)等。C/S架構(gòu)與B/S架構(gòu)示意圖如圖所示。13.1.3網(wǎng)絡(luò)架構(gòu)網(wǎng)絡(luò)架構(gòu)這兩種網(wǎng)絡(luò)架構(gòu)都符合客戶端/服務(wù)器模式,它們最大的區(qū)別在于客戶端是否需要特定的硬件支持。網(wǎng)絡(luò)架構(gòu)13.1.3網(wǎng)絡(luò)架構(gòu)網(wǎng)絡(luò)架構(gòu)中的客戶端主動(dòng)發(fā)出請(qǐng)求,服務(wù)器被動(dòng)地提供服務(wù)。服務(wù)器一般需要永久運(yùn)行,以便能隨時(shí)接收并處理用戶請(qǐng)求;而客戶端只在需要時(shí)啟動(dòng)??蛻舳?服務(wù)器之間可以是一對(duì)一、多對(duì)一的關(guān)系,也可以是多對(duì)多的關(guān)系。

先定一個(gè)小目標(biāo)!了解IP地址和端口號(hào),能夠說(shuō)出它們的作用及特點(diǎn)13.1.4IP地址和端口號(hào)1.IP地址IP地址用于在網(wǎng)絡(luò)上標(biāo)記唯一一臺(tái)計(jì)算機(jī)。網(wǎng)絡(luò)中包含多個(gè)小型的網(wǎng)絡(luò)與眾多主機(jī),若主機(jī)pc1要向主機(jī)pc2發(fā)送信息,那么pc1必須能在這個(gè)網(wǎng)絡(luò)中找到pc2,這要求pc2在整個(gè)網(wǎng)絡(luò)中有一個(gè)唯一標(biāo)識(shí),這個(gè)每臺(tái)主機(jī)在網(wǎng)絡(luò)中的唯一標(biāo)識(shí)就是IP地址。13.1.4IP地址和端口號(hào)1.IP地址由于使用四個(gè)字段表示的IP地址難以閱讀和記憶,人們發(fā)明了域名系統(tǒng),域名系統(tǒng)中的每個(gè)域名都對(duì)應(yīng)唯一一個(gè)IP地址,即使用域名或者與域名對(duì)應(yīng)的IP地址可以訪問(wèn)網(wǎng)絡(luò)上的同一臺(tái)主機(jī)。例如,使用域名“”或者IP地址“4”都能訪問(wèn)百度的主機(jī)。域名和IP地址也被稱為主機(jī)名(hostname)。13.1.4IP地址和端口號(hào)2.端口號(hào)IP地址只能確定網(wǎng)絡(luò)中的主機(jī),要確定主機(jī)中的進(jìn)程,還需用到端口號(hào)(port)。在計(jì)算機(jī)網(wǎng)絡(luò)中,端口號(hào)是一臺(tái)主機(jī)中進(jìn)程的唯一標(biāo)識(shí),因此一個(gè)進(jìn)程在向另一個(gè)進(jìn)程發(fā)送數(shù)據(jù)時(shí),要使用“IP地址+端口號(hào)”確定網(wǎng)絡(luò)中的唯一進(jìn)程。端口號(hào)的最大取值為65535,其中0~1024號(hào)端口一般由系統(tǒng)進(jìn)程占用,用戶可到網(wǎng)絡(luò)相關(guān)資料上查看由國(guó)際因特網(wǎng)地址分配委員會(huì)維護(hù)的官方已分配的端口列表。用戶在編寫自己的服務(wù)器時(shí),可以選擇一個(gè)大于1024、小于65535的端口號(hào)來(lái)標(biāo)識(shí)自己的服務(wù)器,但要注意選擇空閑的端口號(hào),避免與其他服務(wù)器產(chǎn)生沖突。13.1.4IP地址和端口號(hào)socket網(wǎng)絡(luò)編程基礎(chǔ)13.2

先定一個(gè)小目標(biāo)!掌握socket套接字的創(chuàng)建方式,能夠通過(guò)socket()方法創(chuàng)建基于TCP通信的流式套接字13.2.1socket套接字socket()方法Python有一個(gè)名為socket的模塊,該模塊包含了網(wǎng)絡(luò)編程的類、方法、函數(shù)等。利用socket模塊中的構(gòu)造方法socket()可以創(chuàng)建一個(gè)socket對(duì)象,socket()方法的語(yǔ)法格式下:socket(family=AF_INET,type=SOCK_STREAM,proto=0,fileno=None)語(yǔ)法格式13.2.1socket套接字family:用于指定地址族,默認(rèn)值為AF_INET,表示可用于地址為IPv4格式的進(jìn)程間通信。type:用于指定socket的類型,該參數(shù)決定socket的通信方式。proto:用于指定與特定的地址族相關(guān)的協(xié)議,默認(rèn)值為0,表示由系統(tǒng)根據(jù)地址格式和套接字類型自動(dòng)選擇合適的協(xié)議。fileno:用于為套接字文件設(shè)置文件描述符,默認(rèn)設(shè)置為None,表示由系統(tǒng)分配。通過(guò)socket()方法創(chuàng)建socket對(duì)象,示例代碼如下:importsocket#創(chuàng)建socket對(duì)象,指定socket的類型為流式套接字socket_tcp=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#創(chuàng)建socket對(duì)象,指定socket的類型為數(shù)據(jù)報(bào)式套接字socket_udp=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)示例13.2.1socket套接字socket()方法

先定一個(gè)小目標(biāo)!掌握socket套接字的創(chuàng)建方式,能夠通過(guò)socket()方法創(chuàng)建基于TCP通信的流式套接字13.2.2socket通信流程1.面向連接的通信13.2.2socket通信流程根據(jù)socket的類型,網(wǎng)絡(luò)通信又分為基于TCP協(xié)議、面向連接的通信和基于UDP、面向無(wú)連接的通信。面向連接的通信類似日常生活中的電話服務(wù)。在電話服務(wù)中,接電話的一方需要保持電話暢通,以便可隨時(shí)接收他人發(fā)送的通話請(qǐng)求;在電話連通之后,通話的雙方可以開(kāi)始交換數(shù)據(jù)。1.面向連接的通信13.2.2socket通信流程面向連接的通信流程如圖所示。1.面向連接的通信13.2.2socket通信流程在面向連接的通信中,服務(wù)器的工作流程如下:(1)使用socket()方法創(chuàng)建socket對(duì)象;(2)使用bind()方法將服務(wù)器進(jìn)程與端口地址綁定;(3)使用listen()方法開(kāi)啟服務(wù)器監(jiān)聽(tīng);(4)使用accept()方法阻塞等待接受客戶端的連接請(qǐng)求;(4)當(dāng)有客戶端請(qǐng)求遞達(dá)時(shí),使用recv()方法接收客戶端發(fā)送的請(qǐng)求數(shù)據(jù);(5)服務(wù)器處理接收到的數(shù)據(jù),并可能進(jìn)行相應(yīng)的業(yè)務(wù)邏輯處理。(6)處理完成后使用send()方法向客戶端反饋應(yīng)答數(shù)據(jù)(響應(yīng)數(shù)據(jù))。(7)若仍有需求則繼續(xù)進(jìn)行數(shù)據(jù)接收和反饋的操作,否則使用close()方法關(guān)閉socket對(duì)象。需要說(shuō)明的是,由于服務(wù)器需要一直保持運(yùn)行,所以通常情況下服務(wù)器不會(huì)關(guān)閉監(jiān)聽(tīng)的socket。除非遇到特殊情況,例如需要停止服務(wù)器進(jìn)行維護(hù),才會(huì)關(guān)閉服務(wù)器監(jiān)聽(tīng)的socket。1.面向連接的通信13.2.2socket通信流程在面向連接的通信中,客戶端的工作流程如下:(1)使用socket()方法創(chuàng)建socket對(duì)象;(2)使用connect()方法向服務(wù)端發(fā)起連接;(3)連接建立后,使用send()方法向服務(wù)器發(fā)送請(qǐng)求數(shù)據(jù);(4)使用recv()方法接收服務(wù)器返回的應(yīng)答數(shù)據(jù)(響應(yīng)數(shù)據(jù));(5)若仍有需求則繼續(xù)進(jìn)行數(shù)據(jù)發(fā)送和接收的操作,否則使用close()方法關(guān)閉socket對(duì)象,并向服務(wù)器發(fā)送請(qǐng)求結(jié)束通知。2.面向非連接的通信13.2.2socket通信流程面向非連接的通信與生活中的郵件投遞類似。在郵件投遞中,接收郵件的一方無(wú)需一直等待發(fā)送郵件的一方發(fā)起連接請(qǐng)求,發(fā)送郵件的一方只需知道接收方的收件地址,便可直接投遞郵件。同樣,在面向非連接的通信中,接收方無(wú)需主動(dòng)等待發(fā)送方的連接請(qǐng)求,發(fā)送方只需要知道接收方的地址,就可以直接發(fā)送數(shù)據(jù)。2.面向非連接的通信面向非連接的通信流程如圖所示。13.2.2socket通信流程面向非連接的通信流程與面向連接的通信流程大致相同,區(qū)別在于面向非連接的通信中,客戶端不再發(fā)起連接請(qǐng)求,而是使用sendto()方法向指定的服務(wù)器發(fā)送請(qǐng)求數(shù)據(jù);服務(wù)器則使用recvfrom()方法接收數(shù)據(jù),并使用sendto()方法將應(yīng)答數(shù)據(jù)(響應(yīng)數(shù)據(jù))反饋到客戶端。13.2.2socket通信流程2.面向非連接的通信

先定一個(gè)小目標(biāo)!掌握socket內(nèi)置方法,能夠通過(guò)這些方法實(shí)現(xiàn)socket通信13.2.3socket內(nèi)置方法常用內(nèi)置方法13.2.3socket內(nèi)置方法socket模塊為socket對(duì)象定義了一些內(nèi)置方法,通過(guò)這些內(nèi)置方法,可以實(shí)現(xiàn)socket通信,常用的方法如表所示。方法說(shuō)明bind()將套接字與指定的通信地址綁定listen()將套接字變?yōu)楸O(jiān)聽(tīng)套接字,并設(shè)置允許等待接受的最大連接數(shù)setblocking()設(shè)置套接字的阻塞狀態(tài),默認(rèn)為True表示阻塞,F(xiàn)alse表示非阻塞connect()向指定地址發(fā)起連接請(qǐng)求accept()接受連接請(qǐng)求send()/sendto()發(fā)送數(shù)據(jù)/向指定地址的進(jìn)程發(fā)送數(shù)據(jù)recv()/recvfrom()接收數(shù)據(jù)close()關(guān)閉套接字1.bind()方法13.2.3socket內(nèi)置方法確保客戶端能準(zhǔn)確地找到服務(wù)器,服務(wù)器的地址通常是固定的。在創(chuàng)建服務(wù)器的socket后,需要通過(guò)bind()方法將服務(wù)器的socket與服務(wù)器地址綁定,bind()方法的語(yǔ)法格式如下:bind(address)語(yǔ)法格式address:該參數(shù)是一個(gè)形如(hostname,port)的元組,元組中的第一個(gè)元素hostname是一個(gè)字符串,表示主機(jī)地址;第二個(gè)元素port是一個(gè)整數(shù),表示進(jìn)程端口號(hào)。當(dāng)元組中的hostname為空字符串時(shí),進(jìn)程使用本機(jī)的任意IP地址作為主機(jī)地址。假設(shè)當(dāng)前服務(wù)器的socket為socket_server,主機(jī)名為“1”,端口號(hào)為“3456”,那么bind()的用法如下:socket_server.bind(('1',3546))示例13.2.3socket內(nèi)置方法1.bind()方法客戶端的socket也可以調(diào)用bind()方法綁定一個(gè)地址,但因?yàn)榭蛻舳诉M(jìn)程存活時(shí)間相對(duì)較短,且客戶端套接字為主動(dòng)套接字,服務(wù)器在接收數(shù)據(jù)時(shí)動(dòng)態(tài)地獲取客戶端地址已能滿足需求,所以客戶端一般不進(jìn)行此項(xiàng)操作。客戶端進(jìn)程的端口號(hào)通常由系統(tǒng)隨機(jī)分配。2.listen()方法13.2.3socket內(nèi)置方法服務(wù)器的socket應(yīng)被動(dòng)地監(jiān)聽(tīng)客戶端的連接請(qǐng)求,但默認(rèn)情況下套接字工作在主動(dòng)狀態(tài),可主動(dòng)發(fā)送數(shù)據(jù)。調(diào)用listen()方法將使一個(gè)套接字由主動(dòng)狀態(tài)變?yōu)楸粍?dòng)狀態(tài),以等待接收客戶端的連接請(qǐng)求。listen()方法的語(yǔ)法格式如下:listen([backlog])語(yǔ)法格式backlog:該參數(shù)用于指定在拒絕新連接之前,系統(tǒng)允許的未完成連接數(shù)。參數(shù)backlog是可選的,若指定該參數(shù),則它的值至少為0;若缺省該參數(shù),系統(tǒng)會(huì)選擇一個(gè)合理的默認(rèn)值為其賦值。內(nèi)核為監(jiān)聽(tīng)套接字維護(hù)了兩個(gè)隊(duì)列:已連接隊(duì)列和未連接隊(duì)列。完成三次握手過(guò)程的客戶端對(duì)應(yīng)的套接字將被添加到已連接隊(duì)列中,處于半連接狀態(tài)的客戶端對(duì)應(yīng)的套接字將被添加到未連接隊(duì)列中。若未連接隊(duì)列存滿,再有新的客戶端發(fā)起連接請(qǐng)求,該連接請(qǐng)求將被直接拒絕。socket_server.listen(5)示例13.2.3socket內(nèi)置方法2.listen()方法3.connect()方法13.2.3socket內(nèi)置方法connect()方法由客戶端的socket對(duì)象調(diào)用,該方法的功能是向服務(wù)器發(fā)起連接請(qǐng)求。connect()方法的語(yǔ)法格式如下:connect(address)語(yǔ)法格式address:該參數(shù)是一個(gè)形如(hostname,port)的元組,用于指定服務(wù)器的地址。若連接出錯(cuò),connect()方法將返回socket.error錯(cuò)誤。假設(shè)客戶端的socket對(duì)象為client_socket,則connect()方法的用法如下所示:client_socket.connect(('1',3546))示例13.2.3socket內(nèi)置方法3.connect()方法4.accept()方法13.2.3socket內(nèi)置方法accept()方法由服務(wù)器的socket對(duì)象調(diào)用,該方法的功能是處理客戶端發(fā)起的連接請(qǐng)求。accept()方法的語(yǔ)法格式如下:accept()語(yǔ)法格式若調(diào)用accept()方法前沒(méi)有客戶端連接請(qǐng)求到達(dá),accept()方法將會(huì)使服務(wù)器阻塞,直到有客戶端請(qǐng)求連接到達(dá)時(shí)才會(huì)返回;否則accept()方法立即返回一個(gè)形如(conn,address)的元組,元組中conn是新的套接字對(duì)象,用于與相應(yīng)客戶端進(jìn)行數(shù)據(jù)交互,address是客戶端的地址,它的值是一個(gè)形如(hostname,port)的元組。client_socket,address=socket_server.accept()示例send()、sendto()方法用于向目標(biāo)進(jìn)程發(fā)送數(shù)據(jù),它們的語(yǔ)法格式分別如下:13.2.3socket內(nèi)置方法5.send()/sendto()方法send(bytes[,

flags])sendto(bytes,

flags,

address)語(yǔ)法格式send()方法由流式套接字調(diào)用;sendto()方法一般由數(shù)據(jù)報(bào)式套接字調(diào)用。參數(shù)bytes用于設(shè)置要發(fā)送的字節(jié)流數(shù)據(jù),可以通過(guò)以下兩種方式傳遞字節(jié)流數(shù)據(jù):(1)以“b'string'”的形式傳入?yún)?shù),例如傳遞的字符串為“helloitheima”,則send()方法的用法為send(b'helloitheima'),這種方式只能轉(zhuǎn)換ASCII字符。(2)通過(guò)encode()方法對(duì)字符串進(jìn)行轉(zhuǎn)碼,encode()方法中需傳入一個(gè)表示字節(jié)碼格式的參數(shù),比如將字符串轉(zhuǎn)為gb2312編碼的字節(jié)流數(shù)據(jù),則應(yīng)使用語(yǔ)句send('helloitheima'.encode('gb2312'))。參數(shù)flags用于指定發(fā)送數(shù)據(jù)的特殊選項(xiàng),它支持以下幾個(gè)常用取值:socket.MSG_DONTWAIT:非阻塞發(fā)送。socket.MSG_OOB:發(fā)送帶外數(shù)據(jù)。socket.MSG_PEEK:僅查看而不移除接收緩沖區(qū)中的數(shù)據(jù)。socket.MSG_WAITALL:等待直到所有數(shù)據(jù)都被發(fā)送或接收完成。0:默認(rèn)值,不對(duì)發(fā)送操作進(jìn)行特殊處理。flags參數(shù)的值可能因操作系統(tǒng)的不同而有所差異。一般情況下可以不指定flags參數(shù),直接使用默認(rèn)值0即可。13.2.3socket內(nèi)置方法5.send()/sendto()方法sendto()方法中的參數(shù)address本質(zhì)為一個(gè)形如(hostname,port)的元組,用于指定目標(biāo)進(jìn)程的地址。send()、sendto()方法調(diào)用成功都會(huì)返回所發(fā)送數(shù)據(jù)的字節(jié)數(shù),它們的用法如下所示:send(b'helloworld')sendto(b'helloworld',('2',4567))示例13.2.3socket內(nèi)置方法5.send()/sendto()方法13.2.3socket內(nèi)置方法recv()、recvfrom()方法用于接收數(shù)據(jù),它們的語(yǔ)法格式分別如下:recv(bufsize[,

flags])recvfrom(bufsize[,

flags])語(yǔ)法格式6.recv()/recvfrom()方法bufsize:該參數(shù)用于設(shè)置可接收的最大數(shù)據(jù)量。若方法調(diào)用成功,返回接收到的數(shù)據(jù)。recvfrom()方法的參數(shù)bufsize同樣用于設(shè)置可接收的最大數(shù)據(jù)量。若該方法被調(diào)用成功,recvfrom()方法將返回一個(gè)形如(data,address)的元組,元組中data是接收到的數(shù)據(jù),address是發(fā)送數(shù)據(jù)的套接字地址。close()方法用于關(guān)閉套接字。類似于文件,套接字也是系統(tǒng)中的一種資源,使用完畢的套接字應(yīng)及時(shí)關(guān)閉。此外,一臺(tái)主機(jī)中端口的數(shù)量是有限的,系統(tǒng)同樣應(yīng)關(guān)閉空閑的套接字,避免端口浪費(fèi)。client_socket.close()server_socket.close()示例13.2.3socket內(nèi)置方法7.close()方法當(dāng)客戶端終止后,服務(wù)器中與此客戶端交互的套接字也應(yīng)關(guān)閉。一般情況下,若套接字接收到的數(shù)據(jù)為空,則說(shuō)明客戶端進(jìn)程已經(jīng)關(guān)閉連接,因此可通過(guò)判斷接收到的數(shù)據(jù)長(zhǎng)度判斷是否關(guān)閉與客戶端交互的套接字。

先定一個(gè)小目標(biāo)!根據(jù)任務(wù)分析實(shí)現(xiàn)實(shí)例1:掃描開(kāi)放端口13.2.4實(shí)例1:掃描開(kāi)放端口用戶可根據(jù)“IP地址:端口號(hào)”訪問(wèn)網(wǎng)絡(luò)中計(jì)算機(jī)的進(jìn)程,不過(guò)難免有些別有用心之人利用此方式進(jìn)行惡意訪問(wèn)。為避免其他人侵入計(jì)算機(jī),運(yùn)維人員通常會(huì)采取關(guān)閉冗余端口的措施進(jìn)行預(yù)防,但計(jì)算機(jī)中擁有的端口數(shù)量較多,僅靠人力排查的方式顯然是不可取的。因此,考慮通過(guò)編程解決這一問(wèn)題。本實(shí)例要求編寫程序,掃描計(jì)算機(jī)端口,輸出開(kāi)放的端口號(hào)。13.2.4實(shí)例1:掃描開(kāi)放端口使用列表保存價(jià)格信息。定義空列表用于保存用戶選購(gòu)商品的價(jià)格。接收輸入的最大價(jià)格和最小價(jià)格。從價(jià)格列表中獲取每個(gè)商品價(jià)格。判斷商品價(jià)格區(qū)間。將商品價(jià)格進(jìn)行排序。實(shí)現(xiàn)思路13.2.4實(shí)例1:掃描開(kāi)放端口在Chapter13項(xiàng)目中創(chuàng)建01_sacn.py文件。在01_sacn.py中編寫代碼。運(yùn)行01_sacn.py文件。實(shí)現(xiàn)步驟13.2.4實(shí)例1:掃描開(kāi)放端口基于UDP的網(wǎng)絡(luò)聊天室13.3

先定一個(gè)小目標(biāo)!掌握基于UDP的網(wǎng)絡(luò)聊天室功能,能夠?qū)崿F(xiàn)基于UDP的網(wǎng)絡(luò)聊天室13.3基于UDP的網(wǎng)絡(luò)聊天室基于UDP的網(wǎng)絡(luò)聊天室13.3基于UDP的網(wǎng)絡(luò)聊天室defmain():

server_socket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

#創(chuàng)建服務(wù)器的socket

server_socket.bind(("",3456))

#綁定地址

print("-------UDP聊天室-------")

#接收數(shù)據(jù)并輸出

whileTrue:

recv_info=server_socket.recvfrom(1024)

address=recv_info[1][0]+':'+str(recv_info[1][1])

print("%s"%address)

print("%s"%recv_info[0].decode("gb2312"))

server_socket.close()#關(guān)閉服務(wù)器的socket示例聊天窗口是一個(gè)基于UDP協(xié)議的服務(wù)器,編輯框則是一個(gè)基于UDP協(xié)議的客戶端。聊天窗口應(yīng)可接收編輯框發(fā)送來(lái)的數(shù)據(jù),并將發(fā)送數(shù)據(jù)的地址以及數(shù)據(jù)顯示到聊天室中?;赨DP的網(wǎng)絡(luò)聊天室13.3基于UDP的網(wǎng)絡(luò)聊天室defmain():

client_socket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

#創(chuàng)建客戶端的socket

print('----輸入框----')

#向服務(wù)器發(fā)送數(shù)據(jù)

whileTrue:

data=input()

client_socket.sendto(data.encode("gb2312"),("1",3456))

ifdata=='88':

break

client_socket.close()

#關(guān)閉客戶端的socket示例為測(cè)試服務(wù)器接收與處理客戶端數(shù)據(jù)的功能,下面實(shí)現(xiàn)一個(gè)消息編輯發(fā)送功能的客戶端??蛻舳说木唧w實(shí)現(xiàn)如下:基于UDP的網(wǎng)絡(luò)聊天室13.3基于UDP的網(wǎng)絡(luò)聊天室需要說(shuō)明的是,在多臺(tái)計(jì)算機(jī)中進(jìn)行測(cè)試時(shí),計(jì)算機(jī)中的防火墻可能會(huì)過(guò)濾掉來(lái)自其他主機(jī)的UDP客戶端發(fā)送的數(shù)據(jù)包,為保證測(cè)試成功,可先使用“serviceiptablesstop”命令關(guān)閉防火墻,測(cè)試完成后,再通過(guò)“serviceiptablesstart”命令重啟防火墻?;赥CP的數(shù)據(jù)轉(zhuǎn)換13.4

先定一個(gè)小目標(biāo)!掌握基于TCP的數(shù)據(jù)轉(zhuǎn)換功能,能夠?qū)崿F(xiàn)基于TCP的數(shù)據(jù)轉(zhuǎn)換13.4基于TCP的數(shù)據(jù)轉(zhuǎn)換基于TCP的數(shù)據(jù)轉(zhuǎn)換13.4基于TCP的數(shù)據(jù)轉(zhuǎn)換基于TCP的數(shù)據(jù)轉(zhuǎn)換是一種可靠的數(shù)據(jù)傳輸方式。在這種轉(zhuǎn)換中,數(shù)據(jù)被分割成小的數(shù)據(jù)包,并按照順序一個(gè)一個(gè)地通過(guò)TCP連接進(jìn)行發(fā)送和接收,以確保數(shù)據(jù)的完整性和順序性。當(dāng)基于TCP實(shí)現(xiàn)數(shù)據(jù)轉(zhuǎn)換的功能時(shí),數(shù)據(jù)轉(zhuǎn)換程序一般位于服務(wù)器端,它可以接收客戶端發(fā)送的數(shù)據(jù),將這些數(shù)據(jù)進(jìn)行相應(yīng)的轉(zhuǎn)換操作后返回給客戶端。比如,服務(wù)器端接收用戶發(fā)送的字符,將這些字符轉(zhuǎn)換為大寫形式后返回給客戶端,具體如圖所示。13.4基于TCP的數(shù)據(jù)轉(zhuǎn)換基于TCP的數(shù)據(jù)轉(zhuǎn)換實(shí)現(xiàn)基于TCP的數(shù)據(jù)轉(zhuǎn)換程序,用于將客戶端發(fā)送的字符轉(zhuǎn)換為大寫形式的,具體代碼如下:defmain():server_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#創(chuàng)建套接字server_socketserver_socket.bind(("",5678))#綁定地址server_socket.listen(5)#設(shè)置最大連接數(shù)client_socket,address=server_socket.accept()#創(chuàng)建連接print('-----TCP數(shù)據(jù)轉(zhuǎn)換器-----')whileTrue:#接收數(shù)據(jù)recv_info=client_socket.recv(1024).decode('gb2312')string_address=address[0]+':'+str(address[1])13.4基于TCP的數(shù)據(jù)轉(zhuǎn)換基于TCP的數(shù)據(jù)轉(zhuǎn)換實(shí)現(xiàn)基于TCP的數(shù)據(jù)轉(zhuǎn)換程序,用于將客戶端發(fā)送的字符轉(zhuǎn)換為大寫形式的,具體代碼如下:print(string_address)print("待處理數(shù)據(jù):%s"%recv_info)ifrecv_info:#數(shù)據(jù)處理data=recv_info.upper()client_socket.send(data.encode('gb2312'))print("處理結(jié)果:%s"%data)else:print('exit')client_socket.close()breakserver_socket.close()#關(guān)閉套接字server_socket12.4線程的概念線程的概念為測(cè)試該程序的功能,下面實(shí)現(xiàn)一個(gè)用于發(fā)送數(shù)據(jù)和接收數(shù)據(jù)處理結(jié)果的客戶端程序,客戶端程序代碼如下。defmain():client_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#創(chuàng)建套接字client_socketclient_socket.connect(('1',5678))#請(qǐng)求連接#發(fā)送數(shù)據(jù)whileTrue:data=input("-----待處理數(shù)據(jù)------\n")client_socket.send(data.encode('gb2312'))recv_info=client_socket.recv(1024).decode('gb2312')print("------處理結(jié)果-------\n%s"%recv_info)#關(guān)閉套接字client_socketclient_socket.close()多學(xué)一招:端口保留端口保留服務(wù)器在網(wǎng)絡(luò)中的地址是唯一的,因此在為其設(shè)置端口號(hào)時(shí),必須使用主機(jī)中的空閑端口號(hào)。但有時(shí)使用的是空閑端口號(hào),卻還是會(huì)遇到如下所示的問(wèn)題:OSError:[WinError10048]通常每個(gè)套接字地址(協(xié)議/網(wǎng)絡(luò)地址/端口)只允許使用一次。之所以出現(xiàn)上述問(wèn)題,這是因?yàn)槟J(rèn)情況下內(nèi)核會(huì)在進(jìn)程終止的兩分鐘內(nèi)保留進(jìn)程的端口號(hào)。若想解決這一問(wèn)題,可以在創(chuàng)建套接字后,執(zhí)行如下語(yǔ)句:server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)調(diào)用的方法setsockopt()用于設(shè)置套接字的選項(xiàng),當(dāng)其中的第三個(gè)參數(shù)被設(shè)置為1時(shí),服務(wù)器終止后在兩分鐘內(nèi)重新啟動(dòng)可重復(fù)使用同一個(gè)端口。實(shí)例2:TCP文件下載13.5

先定一個(gè)小目標(biāo)!掌握線程的創(chuàng)建與啟動(dòng),能夠通過(guò)threading模塊的Thread類或子類創(chuàng)建線程13.5實(shí)例2:TCP文件下載文件下載是指客戶端將文件從服務(wù)器拷貝到本地。下載文件時(shí),服務(wù)器將根據(jù)客戶端輸入的文件名到指定的目錄中查找,若找到了相應(yīng)的文件,服務(wù)器會(huì)讀取文件,將讀取的內(nèi)容發(fā)送到客戶端;客戶端接收服務(wù)器發(fā)送的數(shù)據(jù),提示用戶選擇下載的位置,并將接收到的數(shù)據(jù)寫入到目標(biāo)位置。本實(shí)例要求編寫程序,實(shí)現(xiàn)基于TCP的文件下載功能。13.5實(shí)例2:TCP文件下載使用列表保存價(jià)格信息。定義空列表用于保存用戶選購(gòu)商品的價(jià)格。接收輸入的最大價(jià)格和最小價(jià)格。從價(jià)格列表中獲取每個(gè)商品價(jià)格。判斷商品價(jià)格區(qū)間。將商品價(jià)格進(jìn)行排序。實(shí)現(xiàn)思路13.5實(shí)例2:TCP文件下載在Chapter13項(xiàng)目中創(chuàng)建tcp_download.py文件。在tcp_download.py中編寫代碼。運(yùn)行tcp_download.py文件。實(shí)現(xiàn)步驟13.5實(shí)例2:TCP文件下載TCP并發(fā)服務(wù)器13.6

先定一個(gè)小目標(biāo)!掌握并發(fā)服務(wù)器,能夠?qū)崿F(xiàn)單進(jìn)程非阻塞服務(wù)器13.6.1單進(jìn)程非阻塞服務(wù)器單進(jìn)程非阻塞服務(wù)器單進(jìn)程非阻塞服務(wù)器通過(guò)解阻塞的方式實(shí)現(xiàn)并發(fā)操作。Python中套接字默認(rèn)以阻塞方式處理數(shù)據(jù),若套接字調(diào)用accept()、recv()等方法時(shí)沒(méi)有接收到數(shù)據(jù),套接字就會(huì)阻塞等待數(shù)據(jù)遞達(dá)。用戶可通過(guò)套接字中提供的setblocking()方法將套接字設(shè)置為非阻塞模式,如此即便套接字中沒(méi)有數(shù)據(jù)遞達(dá),套接字調(diào)用的方法也會(huì)立刻返回。13.6.1單進(jìn)程非阻塞服務(wù)器setblocking()的使用示例如下:13.6.1單進(jìn)程非阻塞服務(wù)器單進(jìn)程非阻塞服務(wù)器server_socket.setblocking(False)示例setblocking()方法中參數(shù)的默認(rèn)值為True,表示套接字默認(rèn)工作在阻塞模式。以上示例中的參數(shù)的值為False,用于將套接字設(shè)置為非阻塞模式。若要使服務(wù)器可以與多個(gè)客戶端建立連接,需要保證在調(diào)用accept()方法時(shí)不會(huì)產(chǎn)生阻塞,即服務(wù)器套接字server_socket應(yīng)被設(shè)置為非阻塞;若要使每個(gè)連接中的客戶端都可隨時(shí)向服務(wù)器中發(fā)送數(shù)據(jù),則需保證在調(diào)用recv()方法時(shí)不產(chǎn)生阻塞,即新套接字new_socket應(yīng)被設(shè)置為非阻塞。

先定一個(gè)小目標(biāo)!掌握并發(fā)服務(wù)器,能夠?qū)崿F(xiàn)多進(jìn)程并發(fā)服務(wù)器13.6.2多進(jìn)程并發(fā)服務(wù)器多進(jìn)程并發(fā)服務(wù)器多進(jìn)程并發(fā)服務(wù)器中的主進(jìn)程用于處理客戶端的連接請(qǐng)求,當(dāng)有新的客戶端與服務(wù)器建立連接后,服務(wù)器會(huì)創(chuàng)建一個(gè)子進(jìn)程,由子進(jìn)程完成數(shù)據(jù)的交互工作。13.6.2多進(jìn)程并發(fā)服務(wù)器線程鎖概述13.6.2多進(jìn)程并發(fā)服務(wù)器以將小寫字符串轉(zhuǎn)為大寫字符串的服務(wù)器為例,實(shí)現(xiàn)多進(jìn)程并發(fā)服務(wù)器。importsocket,multiprocessingdefdeal_with_client(new_socket,client_address):whileTrue:recv_data=new_socket.recv(1024).decode('gb2312')iflen(recv_data)>0:print('待處理數(shù)據(jù):%s:%s'%(str(client_address),recv_data))data=recv_data.upper()new_socket.send(data.encode('gb2312'))else:print('客戶端[%s]已關(guān)閉'%str(client_address))breaknew_socket.close()線程鎖概述13.6.2多進(jìn)程并發(fā)服務(wù)器以將小寫字符串轉(zhuǎn)為大寫字符串的服務(wù)器為例,實(shí)現(xiàn)多進(jìn)程并發(fā)服務(wù)器。defmain():server_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#創(chuàng)建服務(wù)器套接字server_socketserver_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)#端口快速重啟用local_address=('',8081)server_socket.bind(local_address)server_socket.listen(5)print('-----服務(wù)器------')

續(xù)...線程鎖概述13.6.2多進(jìn)程并發(fā)服務(wù)器以將小寫字符串轉(zhuǎn)為大寫字符串的服務(wù)器為例,實(shí)現(xiàn)多進(jìn)程并發(fā)服務(wù)器。

續(xù)...try:whileTrue:#處理客戶端連接請(qǐng)求new_socket,client_address=server_socket.accept()print('一個(gè)新的客戶端到達(dá)[%s]'%str(client_address))#創(chuàng)建子進(jìn)程與客戶端進(jìn)行交互client=multiprocessing.Process(target=deal_with_client,rgs=(new_socket,client_address))client.start()new_socket.close()#關(guān)閉父進(jìn)程中的套接字new_socketfinally:server_socket.close()#關(guān)閉服務(wù)器套接字線程鎖概述13.6.2多進(jìn)程并發(fā)服務(wù)器為測(cè)試此段服務(wù)器代碼,這里實(shí)現(xiàn)一個(gè)可向服務(wù)器發(fā)送數(shù)據(jù),并接收服務(wù)器反饋數(shù)據(jù)的客戶端??蛻舳说拇a實(shí)現(xiàn)如下:importsocketdefmain():client_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#創(chuàng)建套接字client_socketclient_socket.connect(('1',8081))#請(qǐng)求連接whileTrue:#發(fā)送數(shù)據(jù)

溫馨提示

  • 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)論