本篇文章主要介紹了python實(shí)現(xiàn)簡(jiǎn)單的httpserver服務(wù)器示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
要寫(xiě)一個(gè)類(lèi)似tomcat的簡(jiǎn)易服務(wù)器,首先需弄清楚這幾點(diǎn):
1. 客戶(hù)端(Client)和服務(wù)端(Server)的角色及作用
角色A向角色B請(qǐng)求數(shù)據(jù),這時(shí)可以把A視為客戶(hù)端,B視為服務(wù)端??蛻?hù)端的主要職責(zé)是發(fā)送請(qǐng)求和接收服務(wù)端根據(jù)自己發(fā)送的請(qǐng)求返回的請(qǐng)求信息,而服務(wù)端的主要職責(zé)是接收請(qǐng)求和返回請(qǐng)求數(shù)據(jù)。
2. 瀏覽器是什么及工作原理
立即學(xué)習(xí)“Python免費(fèi)學(xué)習(xí)筆記(深入)”;
我們常說(shuō)B/S,C/S架構(gòu),所謂的B/S指browser/server,C/S指Client/Server,B/S架構(gòu)其實(shí)就是應(yīng)用于瀏覽器的程序,只要最后在瀏覽器上展現(xiàn)的都是 B/S架構(gòu),而非在瀏覽器上展現(xiàn)的都是C/S架構(gòu),如常見(jiàn)的英雄聯(lián)盟游戲。但是本質(zhì)上只有C/S架構(gòu),因?yàn)闉g覽器是一種特殊的客戶(hù)端。
瀏覽器的特殊之處是有一下三大引擎:
DOM解析引擎:即瀏覽器可以解析HTML
樣式解析引擎:即瀏覽器可以解析CSS
腳本解析引擎:即瀏覽器可以解析JAVASCRIPT
3. Socket
上面提到的客戶(hù)端服務(wù)端,他們之間是怎樣實(shí)現(xiàn)連接及數(shù)據(jù)傳遞的,這就是Socket,每一門(mén)編程語(yǔ)言都有Socket編程,Socket的作用就是提供了網(wǎng)絡(luò)通信的能力
4. HTTP協(xié)議及HTTP與TCP/TP的區(qū)別
客戶(hù)端和服務(wù)端通過(guò)Socket實(shí)現(xiàn)了網(wǎng)絡(luò)通信的能力,可以實(shí)現(xiàn)數(shù)據(jù)傳遞。而協(xié)議是規(guī)范數(shù)據(jù)傳輸,也就是說(shuō)客戶(hù)端和服務(wù)端之間傳輸數(shù)據(jù)要按照一定得規(guī)范和標(biāo)準(zhǔn)傳輸,不能瞎傳。
TCP/IP(Transmission Control Protocol/Internet Protocol):傳輸控制協(xié)議/網(wǎng)間協(xié)議
HTTP(HyperText Transfer Protocol):超文本傳輸協(xié)議。
TCP/TP的區(qū)別:
做一個(gè)形象的比喻,TCP/TP是馬路,HTTP則是馬路上的汽車(chē),所以HTTP一定是在TCP/TP的基礎(chǔ)上的。
HTTP主要是應(yīng)用在web程序上,設(shè)計(jì)之初就是為了提供一種發(fā)布和接收HTML頁(yè)面的方法,這樣說(shuō)可能很抽象很難理解。具體的說(shuō)當(dāng)我們?nèi)ピL(fǎng)問(wèn)一個(gè)網(wǎng)站時(shí),只需要拿到基于這個(gè)網(wǎng)站的內(nèi)容(比如html,css,JavaScript)。但我們抓取瀏覽器接收到的資源包(可以用Fiddler工具)發(fā)現(xiàn)除了網(wǎng)頁(yè)需要的實(shí)體內(nèi)容還有一些下面信息:
HTTP/1.1 200 OK
?Cache-Control: private
?Content-Type: text/plain; charset=utf-8
?Content-Encoding: gzip
?Vary: Accept-Encoding
?Server: Microsoft-IIS/7.5
?X-AspNet-Version: 4.0.30319
?X-Powered-By: ASP.NET
?Date: Tue, 24 Jan 2017 03:25:23 GMT
?Connection: close
?Content-Length: 661
這就是http協(xié)議規(guī)范,比如Content-Type就是說(shuō)傳輸?shù)臅r(shí)候文件的格式,Content-Encoding規(guī)定了編碼格式。不止以上這些,非常多,關(guān)于這些參數(shù)含義這里就不去一一介紹
5. URL的含義
URL(統(tǒng)一資源定位符),就是我們常說(shuō)的網(wǎng)址,直接來(lái)解析一個(gè)URL來(lái)說(shuō)明他:http://198.2.17.25:8080/webapp/index.html
這個(gè)含義是找到IP為198.2.17.25的服務(wù)器下目錄為webapp的index.html
但是我們常看到的是這樣的URL:http://goodcandle.cnblogs.com/archive/2005/12/10/294652.aspx
其實(shí)這個(gè)和上面的一樣,不過(guò)這里存在一個(gè)域名解析,可以將goodcandle.cnblogs.com解析成對(duì)應(yīng)的IP地址
弄清楚以上五點(diǎn)之后開(kāi)始來(lái)寫(xiě)代碼
webServer.py
import socket import sys import getFileContent #聲明一個(gè)將要綁定的IP和端口,這里是用本地地址 server_address = ('localhost', 8080) class WebServer(): def run(self): print >>sys.stderr, 'starting up on %s port %s' % server_address #實(shí)例化一個(gè)Socket sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #綁定IP和端口 sock.bind(server_address) #設(shè)置監(jiān)聽(tīng) sock.listen(1) #這里首先給個(gè)死循環(huán),其實(shí)這里是需要多線(xiàn)程的,再后續(xù)版本將會(huì)實(shí)現(xiàn) while True: #接受客戶(hù)端的請(qǐng)求并得到請(qǐng)求信息和請(qǐng)求的端口信息 connection, client_address = sock.accept() print >>sys.stderr, 'waiting for a connection' try: #獲取請(qǐng)求信息 data = connection.recv(1024) if data: #發(fā)送請(qǐng)求信息 connection.sendall(getFileContent.getHtmlFile(data)) finally: connection.close() if __name__ == '__main__': server=WebServer() server.run()
webServer.py很清晰簡(jiǎn)潔,connection.sendall()
服務(wù)端返回信息給瀏覽器,但是發(fā)送的數(shù)據(jù)必須遵循HTTP協(xié)議規(guī)范
getFileContent.py是對(duì)發(fā)送的數(shù)據(jù)進(jìn)行HTTP協(xié)議規(guī)范處理
import sys import os #得到要發(fā)送的數(shù)據(jù)信息 def getHtmlFile(data): msgSendtoClient="" requestType=data[0:data.find("/")].rstrip() #判斷是GET請(qǐng)求還是POST請(qǐng)求 if requestType=="GET": msgSendtoClient=responseGetRequest(data,msgSendtoClient) if requestType=="POST": msgSendtoClient=responsePostRequest(data,msgSendtoClient) return msgSendtoClient #打開(kāi)文件,這里不直接寫(xiě),二是去取要發(fā)送的文件再寫(xiě) def getFile(msgSendtoClient,file): for line in file: msgSendtoClient+=line return msgSendtoClient #篩選出請(qǐng)求的一個(gè)方法 def getMidStr(data,startStr,endStr): startIndex = data.index(startStr) if startIndex>=0: startIndex += len(startStr) endIndex = data.index(endStr) return data[startIndex:endIndex] #獲取要發(fā)送數(shù)據(jù)的大小,根據(jù)HTTP協(xié)議規(guī)范,要提前指定發(fā)送的實(shí)體內(nèi)容的大小 def getFileSize(fileobject): fileobject.seek(0,2) size = fileobject.tell() return size #設(shè)置編碼格式和文件類(lèi)型 def setParaAndContext(msgSendtoClient,type,file,openFileType): msgSendtoClient+="Content-Type: "+type+";charset=utf-8" msgSendtoClient+="Content-Length: "+str(getFileSize(open(file,"r")))+"\n"+"\n" htmlFile=open(file,openFileType) msgSendtoClient=getFile(msgSendtoClient,htmlFile) return msgSendtoClient #GET請(qǐng)求的返回?cái)?shù)據(jù) def responseGetRequest(data,msgSendtoClient): return responseRequest(getMidStr(data,'GET /','HTTP/1.1'),msgSendtoClient) #POST請(qǐng)求的返回?cái)?shù)據(jù) def responsePostRequest(data,msgSendtoClient): return responseRequest(getMidStr(data,'POST /','HTTP/1.1'),msgSendtoClient) #請(qǐng)求返回?cái)?shù)據(jù) def responseRequest(getRequestPath,msgSendtoClient): headFile=open("head.txt","r") msgSendtoClient=getFile(msgSendtoClient,headFile) if getRequestPath==" ": msgSendtoClient=setParaAndContext(msgSendtoClient,"text/html","index.html","r") else: rootPath=getRequestPath if os.path.exists(rootPath) and os.path.isfile(rootPath): if ".html" in rootPath: msgSendtoClient=setParaAndContext(msgSendtoClient,"text/html",rootPath,"r") if ".css" in rootPath: msgSendtoClient=setParaAndContext(msgSendtoClient,"text/css",rootPath,"r") if ".js" in rootPath: msgSendtoClient=setParaAndContext(msgSendtoClient,"application/x-javascript",rootPath,"r") if ".gif" in rootPath: msgSendtoClient=setParaAndContext(msgSendtoClient,"image/gif",rootPath,"rb") if ".doc" in rootPath: msgSendtoClient=setParaAndContext(msgSendtoClient,"application/msword",rootPath,"rb") if ".mp4" in rootPath: msgSendtoClient=setParaAndContext(msgSendtoClient,"video/mpeg4",rootPath,"rb") else: msgSendtoClient=setParaAndContext(msgSendtoClient,"application/x-javascript","file.js","r") return msgSendtoClient
以上就是Python實(shí)現(xiàn)簡(jiǎn)單的HttpServer服務(wù)器的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注php中文網(wǎng)其它相關(guān)文章!
python怎么學(xué)習(xí)?python怎么入門(mén)?python在哪學(xué)?python怎么學(xué)才快?不用擔(dān)心,這里為大家提供了python速學(xué)教程(入門(mén)到精通),有需要的小伙伴保存下載就能學(xué)習(xí)啦!
微信掃碼
關(guān)注PHP中文網(wǎng)服務(wù)號(hào)
QQ掃碼
加入技術(shù)交流群
Copyright 2014-2025 http://ipnx.cn/ All Rights Reserved | php.cn | 湘ICP備2023035733號(hào)