使用Socket在Python中設(shè)置Internet服務(wù)器

01

10 8

插座介紹

作為網(wǎng)絡(luò)客戶端教程的補(bǔ)充,本教程介紹了如何使用Python實(shí)現(xiàn)簡(jiǎn)單的web服務(wù)器。可以肯定的是,這不能替代Apache或Zope。還有更強(qiáng)大的方法可以使用BaseHTTPServer等模塊在Python中實(shí)現(xiàn)web服務(wù)。該服務(wù)器僅使用插座模塊。

您將記得socket模塊是大多數(shù)Python web服務(wù)模塊的骨干。與簡(jiǎn)單的網(wǎng)絡(luò)客戶端一樣,使用它構(gòu)建服務(wù)器可以透明地說(shuō)明Python中web服務(wù)的基礎(chǔ)知識(shí)。BaseHTTP服務(wù)器本身會(huì)導(dǎo)入socket模塊以影響服務(wù)器。

02

33 of 10 34

運(yùn)行服務(wù)器

通過(guò)審查,所有網(wǎng)絡(luò)事務(wù)都發(fā)生在客戶端和服務(wù)器之間。在大多數(shù)協(xié)議中,客戶端詢問(wèn)某個(gè)地址并接收數(shù)據(jù)。

在每個(gè)地址內(nèi),可以運(yùn)行多個(gè)服務(wù)器。限制在硬件中。有了足夠的硬件(RAM,處理器速度等),同一臺(tái)計(jì)算機(jī)可以同時(shí)用作web服務(wù)器,ftp服務(wù)器和郵件服務(wù)器(pop,SMP,imap或以上所有)。每個(gè)服務(wù)都與一個(gè)端口相關(guān)聯(lián)。該端口綁定到插座。服務(wù)器監(jiān)視其關(guān)聯(lián)的端口,并在該端口上收到請(qǐng)求時(shí)提供信息。

03

59 of 10 60

通過(guò)插座進(jìn)行通信

因此,要影響網(wǎng)絡(luò)連接,您需要了解主機(jī),端口以及該端口上允許的操作。大多數(shù)web服務(wù)器在端口80上運(yùn)行。但是,為了避免與已安裝的Apache服務(wù)器發(fā)生沖突,我們的web服務(wù)器將在端口8080上運(yùn)行。為了避免與其他服務(wù)發(fā)生沖突,最好將HTTP服務(wù)保留在端口80或8080上。這是兩個(gè)最常見(jiàn)的。Obvi當(dāng)然,如果使用這些,您必須找到一個(gè)開(kāi)放端口并提醒用戶進(jìn)行更改。

與網(wǎng)絡(luò)客戶端一樣,您應(yīng)該注意這些地址是不同服務(wù)的通用端口號(hào)。只要客戶端在正確的地址要求正確的端口上提供正確的服務(wù),通信仍然會(huì)發(fā)生。例如,Google's郵件服務(wù)最初并未使用通用端口號(hào)運(yùn)行,但由于他們知道如何訪問(wèn)帳戶,因此用戶仍然可以獲取郵件。

與網(wǎng)絡(luò)客戶端不同,服務(wù)器中的所有變量都是硬連線的。任何預(yù)期不斷運(yùn)行的服務(wù)都不應(yīng)在命令行中設(shè)置其內(nèi)部邏輯的變量。**的變化是,出于某種原因,您希望服務(wù)偶爾運(yùn)行并使用各種端口號(hào)。但是,如果是這種情況,您仍然可以查看系統(tǒng)時(shí)間并相應(yīng)更改綁定。

所以我們**的進(jìn)口是插座模塊。


導(dǎo)入插座

接下來(lái),我們需要聲明一些變量。

04

of 10

主機(jī)和端口

如前所述,服務(wù)器需要知道要關(guān)聯(lián)的主機(jī)以及要聆聽(tīng)的端口。為了我們的目的,我們將該服務(wù)完全適用于任何主機(jī)名。

教育_1

主機(jī)=''
端口=8080

如前所述,該端口將是8080。所以請(qǐng)注意,如果您將此服務(wù)器與網(wǎng)絡(luò)客戶端結(jié)合使用,則需要更改該程序中使用的端口號(hào)。

05

120 of 10 121

創(chuàng)建一個(gè)插座

無(wú)論是請(qǐng)求信息還是服務(wù)信息,為了訪問(wèn)互聯(lián)網(wǎng),我們需要?jiǎng)?chuàng)建一個(gè)插座。此調(diào)用的語(yǔ)法如下知識(shí)健康講座


=插座(,

公認(rèn)的插座系列是:

  • AF?INET:IP4協(xié)議(TCP和UDP)
  • AF?INET6:IP6協(xié)議(TCP和UDP)
  • AF?UNIX:UNIX域協(xié)議

前兩個(gè)顯然是互聯(lián)網(wǎng)協(xié)議。在這些家庭中可以訪問(wèn)通過(guò)互聯(lián)網(wǎng)傳播的任何內(nèi)容。許多網(wǎng)絡(luò)仍然不在IP6上運(yùn)行。因此,除非另有說(shuō)明,否則默認(rèn)為IP4并使用AF?INET是最安全的。

插座類型是指通過(guò)插座使用的通信類型。五種插座類型如下:

  • SOCK?STREAM:a connection-oriented,TCP byte STREAM
  • SOCK?DGRAM:UDP transferral of datagrams(獨(dú)立于客戶端-服務(wù)器確認(rèn)的IP數(shù)據(jù)包)
  • SOCK?RAW:a RAW SOCK
  • SOCK?RDM:for reable datagrams
  • SOCK?seqpackade:sequential transfer of records over a connection

到目前為止,最常見(jiàn)的類型是襪子和襪子,因?yàn)樗鼈冊(cè)贗P套件的兩個(gè)協(xié)議(TCP和UDP)上運(yùn)行。后三種情況要少得多,因此可能并不總是得到支持。

所以讓's創(chuàng)建一個(gè)插座并將其分配給一個(gè)變量。


c=插座(socket.AF?INET, SOCK.SOCK?u流)

06

178 of 10 179

設(shè)置插座選項(xiàng)

創(chuàng)建插座后,我們需要設(shè)置插座選項(xiàng)。對(duì)于任何插座對(duì)象,您可以使用setsockopt()方法設(shè)置插座選項(xiàng)。語(yǔ)法如下:

插座_對(duì)象(級(jí)別,選項(xiàng)名稱,值)出于我們的目的,我們使用以下行:

c.setsockopt(socket.SOL?u插座, socket.SO?REUSEADDR,1)

術(shù)語(yǔ)'level'是指選項(xiàng)的類別。對(duì)于插座級(jí)選項(xiàng),請(qǐng)使用SOL?插座。對(duì)于協(xié)議編號(hào),人們會(huì)使用IPPROTO?IP。SOL?u插座是插座的恒定屬性。確切地說(shuō),作為每個(gè)級(jí)別的一部分,哪些選項(xiàng)是由您的操作系統(tǒng)以及您是使用IP4還是IP6決定的。
Linux和相關(guān)Unix系統(tǒng)的文檔可以在系統(tǒng)文檔中找到。Microsoft用戶的文檔可以在MSDN網(wǎng)站上找到。在撰寫本文時(shí),我還沒(méi)有找到有關(guān)插座編程的Mac文檔。由于Mac大致基于BSD Unix,因此它可能實(shí)現(xiàn)完整的選項(xiàng)補(bǔ)充。
為了確保此插座的可重用性,我們使用了sou REUSEADDR選項(xiàng)??梢詫⒎?wù)器限制為僅在開(kāi)放端口上運(yùn)行,但這似乎是不必要的。但是請(qǐng)注意,如果在同一個(gè)端口上部署了兩個(gè)或多個(gè)服務(wù),則效果是不可預(yù)測(cè)的。人們無(wú)法確定哪個(gè)服務(wù)將接收哪個(gè)信息包。
最后,'1'對(duì)于一個(gè)值是在程序中已知對(duì)插座的請(qǐng)求的值。通過(guò)這種方式,程序可以非常細(xì)致地聽(tīng)到插座。

07

of 10

將端口綁定到插座

創(chuàng)建插座并設(shè)置其選項(xiàng)后,我們需要將端口綁定到插座。


c.bind((主機(jī),端口))

綁定完成后,我們現(xiàn)在告訴計(jì)算機(jī)等待并傾聽(tīng)該端口。


c.傾聽(tīng)(1)

如果我們想向調(diào)用服務(wù)器的人提供反饋,我們現(xiàn)在可以輸入打印命令以確認(rèn)服務(wù)器正在運(yùn)行。

08

10 239中的238個(gè)

處理服務(wù)器請(qǐng)求

設(shè)置服務(wù)器后,我們現(xiàn)在需要告訴Python在給定端口上發(fā)出請(qǐng)求時(shí)要做什么。為此,我們按其值引用請(qǐng)求,并將其用作持久性while循環(huán)的參數(shù)。

發(fā)出請(qǐng)求時(shí),服務(wù)器應(yīng)接受該請(qǐng)求并創(chuàng)建一個(gè)與之交互的file對(duì)象。

而1:
csock,caddr=c.accept()
cfile=csock.makefile('rw',0)

在這種情況下,服務(wù)器使用相同的端口進(jìn)行讀寫。因此,makefile方法被賦予一個(gè)參數(shù)'rw'。緩沖區(qū)大小的空長(zhǎng)度只是留下部分文件動(dòng)態(tài)確定。

09

of 10

將數(shù)據(jù)發(fā)送到客戶端

除非我們想創(chuàng)建單個(gè)操作服務(wù)器,否則下一步是從file對(duì)象讀取輸入。當(dāng)我們這樣做時(shí),我們應(yīng)該小心去除多余的空白輸入。

line=cfile.readline()。剝離()

請(qǐng)求將以操作的形式出現(xiàn),然后是頁(yè)面,協(xié)議和正在使用的協(xié)議的版本。如果想要提供網(wǎng)頁(yè),可以分割這個(gè)輸入來(lái)檢索請(qǐng)求的頁(yè)面,然后將該頁(yè)面讀取到一個(gè)變量中,然后寫入socket file對(duì)象。博客中可以找到將文件讀入字典的功能。

為了使本教程更詳細(xì)地說(shuō)明如何使用socket模塊,我們將放棄服務(wù)器的這一部分,而是展示如何使數(shù)據(jù)呈現(xiàn)細(xì)微差別。在程序中輸入接下來(lái)的幾行。

cfile.write('HTTP/1.0 200 OK \ n \ n')
cfile.write('歡迎%s! '%(str(caddr)))
cfile.write('

按照鏈接…

')
cfile.write('所有服務(wù)器需要做的是')
cfile.write('將文本傳送到插座。')
cfile.write('它提供鏈接的HTML代碼,')
cfile.write('web瀏覽器對(duì)其進(jìn)行轉(zhuǎn)換。&升t、 br>

')
cfile.write('

點(diǎn)擊我!
')
cfile.write('

您的請(qǐng)求措辭為:"%s"'%(行))
cfile.write('<#body><#html>')

10

10 302中的301

最終分析并關(guān)閉

如果發(fā)送網(wǎng)頁(yè),第一行是將數(shù)據(jù)引入web瀏覽器的好方法。如果省略,大多數(shù)web瀏覽器將默認(rèn)為渲染HTML。但是,如果包含它,'OK'必須后跟兩個(gè)新行字符。這些用于區(qū)分協(xié)議信息和頁(yè)面內(nèi)容。

正如您可能推測(cè)的那樣,第一行的語(yǔ)法是協(xié)議,協(xié)議版本,消息編號(hào)和狀態(tài)。如果您曾經(jīng)訪問(wèn)過(guò)已移動(dòng)的網(wǎng)頁(yè),則可能收到404錯(cuò)誤。這里的200條信息只是肯定的信息。

其余的輸出只是一個(gè)分為幾行的網(wǎng)頁(yè)。您將注意到可以對(duì)服務(wù)器進(jìn)行編程以使用輸出中的用戶數(shù)據(jù)。最后一行反映了服務(wù)器收到的web請(qǐng)求。

最后,作為請(qǐng)求的關(guān)閉行為,我們需要關(guān)閉file對(duì)象和服務(wù)器插座。

cfile.close()
csock.close()

現(xiàn)在以可識(shí)別的名稱保存此程序。用'調(diào)用它后;python程序_name.py',如果您編程了確認(rèn)服務(wù)正在運(yùn)行的消息,則應(yīng)打印到屏幕上。終端似乎會(huì)暫停。一切都是應(yīng)該的。打開(kāi)您的web瀏覽器并轉(zhuǎn)到本地主機(jī):8080。然后你應(yīng)該看到我們給出的寫入命令的輸出。請(qǐng)注意,為了空間,我沒(méi)有暗示此程序中的nt錯(cuò)誤處理。但是,任何發(fā)布到'wild'的程序都應(yīng)該。