Python實(shí)現(xiàn)簡單的HttpServer服務(wù)器示例
要寫一個(gè)類似tomcat的簡易服務(wù)器,首先需弄清楚這幾點(diǎn):
1. 客戶端(Client)和服務(wù)端(Server)的角色及作用
角色A向角色B請求數(shù)據(jù),這時(shí)可以把A視為客戶端,B視為服務(wù)端??蛻舳说闹饕氊?zé)是發(fā)送請求和接收服務(wù)端根據(jù)自己發(fā)送的請求返回的請求信息,而服務(wù)端的主要職責(zé)是接收請求和返回請求數(shù)據(jù)。
2. 瀏覽器是什么及工作原理
我們常說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),如常見的英雄聯(lián)盟游戲。但是本質(zhì)上只有C/S架構(gòu),因?yàn)闉g覽器是一種特殊的客戶端。
瀏覽器的特殊之處是有一下三大引擎:
- DOM解析引擎:即瀏覽器可以解析HTML
- 樣式解析引擎:即瀏覽器可以解析CSS
- 腳本解析引擎:即瀏覽器可以解析JAVASCRIPT
3. Socket
上面提到的客戶端服務(wù)端,他們之間是怎樣實(shí)現(xiàn)連接及數(shù)據(jù)傳遞的,這就是Socket,每一門編程語言都有Socket編程,Socket的作用就是提供了網(wǎng)絡(luò)通信的能力
4. HTTP協(xié)議及HTTP與TCP/TP的區(qū)別
客戶端和服務(wù)端通過Socket實(shí)現(xiàn)了網(wǎng)絡(luò)通信的能力,可以實(shí)現(xiàn)數(shù)據(jù)傳遞。而協(xié)議是規(guī)范數(shù)據(jù)傳輸,也就是說客戶端和服務(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則是馬路上的汽車,所以HTTP一定是在TCP/TP的基礎(chǔ)上的。
HTTP主要是應(yīng)用在web程序上,設(shè)計(jì)之初就是為了提供一種發(fā)布和接收HTML頁面的方法,這樣說可能很抽象很難理解。具體的說當(dāng)我們?nèi)ピL問一個(gè)網(wǎng)站時(shí),只需要拿到基于這個(gè)網(wǎng)站的內(nèi)容(比如html,css,JavaScript)。但我們抓取瀏覽器接收到的資源包(可以用Fiddler工具)發(fā)現(xiàn)除了網(wǎng)頁需要的實(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就是說傳輸?shù)臅r(shí)候文件的格式,Content-Encoding規(guī)定了編碼格式。不止以上這些,非常多,關(guān)于這些參數(shù)含義這里就不去一一介紹
5. URL的含義
URL(統(tǒng)一資源定位符),就是我們常說的網(wǎng)址,直接來解析一個(gè)URL來說明他: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è)和上面的一樣,不過這里存在一個(gè)域名解析,可以將goodcandle.cnblogs.com解析成對應(yīng)的IP地址
弄清楚以上五點(diǎn)之后開始來寫代碼
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)聽
sock.listen(1)
#這里首先給個(gè)死循環(huán),其實(shí)這里是需要多線程的,再后續(xù)版本將會(huì)實(shí)現(xiàn)
while True:
#接受客戶端的請求并得到請求信息和請求的端口信息
connection, client_address = sock.accept()
print >>sys.stderr, 'waiting for a connection'
try:
#獲取請求信息
data = connection.recv(1024)
if data:
#發(fā)送請求信息
connection.sendall(getFileContent.getHtmlFile(data))
finally:
connection.close()
if __name__ == '__main__':
server=WebServer()
server.run()
webServer.py很清晰簡潔,connection.sendall()服務(wù)端返回信息給瀏覽器,但是發(fā)送的數(shù)據(jù)必須遵循HTTP協(xié)議規(guī)范
getFileContent.py是對發(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請求還是POST請求
if requestType=="GET":
msgSendtoClient=responseGetRequest(data,msgSendtoClient)
if requestType=="POST":
msgSendtoClient=responsePostRequest(data,msgSendtoClient)
return msgSendtoClient
#打開文件,這里不直接寫,二是去取要發(fā)送的文件再寫
def getFile(msgSendtoClient,file):
for line in file:
msgSendtoClient+=line
return msgSendtoClient
#篩選出請求的一個(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è)置編碼格式和文件類型
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請求的返回?cái)?shù)據(jù)
def responseGetRequest(data,msgSendtoClient):
return responseRequest(getMidStr(data,'GET /','HTTP/1.1'),msgSendtoClient)
#POST請求的返回?cái)?shù)據(jù)
def responsePostRequest(data,msgSendtoClient):
return responseRequest(getMidStr(data,'POST /','HTTP/1.1'),msgSendtoClient)
#請求返回?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
Github源碼下載:https://github.com/Jiashengp/Python_httpServer
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 使用 Python 快速實(shí)現(xiàn) HTTP 和 FTP 服務(wù)器的方法
- Python通過命令開啟http.server服務(wù)器的方法
- python探索之BaseHTTPServer-實(shí)現(xiàn)Web服務(wù)器介紹
- Python探索之實(shí)現(xiàn)一個(gè)簡單的HTTP服務(wù)器
- Python搭建HTTP服務(wù)器和FTP服務(wù)器
- Python實(shí)現(xiàn)批量檢測HTTP服務(wù)的狀態(tài)
- Python內(nèi)置的HTTP協(xié)議服務(wù)器SimpleHTTPServer使用指南
- 使用Python來編寫HTTP服務(wù)器的超級指南
- 超簡單的Python HTTP服務(wù)
相關(guān)文章
Python機(jī)器學(xué)習(xí)之PCA降維算法詳解
今天帶大家復(fù)習(xí)python機(jī)器學(xué)習(xí)的知識(shí)點(diǎn),文中對PCA降維算法介紹的非常詳細(xì),對正在學(xué)習(xí)python機(jī)器學(xué)習(xí)的小伙伴們有很好地幫助,需要的朋友可以參考下2021-05-05
Python中的list.sort()方法和函數(shù)sorted(list)
這篇文章主要介紹了Python中的list.sort()方法和函數(shù)sorted(list),sort()是列表的方法,修改原列表使得它按照大小排序,沒有返回值,返回None2022-08-08
Python爬蟲學(xué)習(xí)之獲取指定網(wǎng)頁源碼
這篇文章主要為大家詳細(xì)介紹了Python爬蟲學(xué)習(xí)之獲取指定網(wǎng)頁源碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07
python中l(wèi)ogging包的使用總結(jié)
本篇文章給大家詳細(xì)講述了python中l(wèi)ogging包的使用的相關(guān)知識(shí)點(diǎn)以及原理分析,有興趣的朋友可以參考學(xué)習(xí)下。2018-02-02
淺談Python中重載isinstance繼承關(guān)系的問題
本篇文章主要介紹了淺談Python中重載isinstance繼承關(guān)系的問題,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-05-05
教你用Python pygame設(shè)置窗口標(biāo)題和圖標(biāo)
今天給大家?guī)淼氖顷P(guān)于Python的相關(guān)知識(shí),文章圍繞著用Python pygame設(shè)置窗口標(biāo)題和圖標(biāo)展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-06-06
利用python實(shí)現(xiàn)平穩(wěn)時(shí)間序列的建模方式
這篇文章主要介紹了利用python實(shí)現(xiàn)平穩(wěn)時(shí)間序列的建模方式,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-06-06

