成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

寫一個簡單的webserver

yuanxin / 1771人閱讀

摘要:基于寫的極簡版。服務(wù)器是屬于被動的一方,當(dāng)瀏覽器發(fā)起請求的時候,服務(wù)器才能和瀏覽器通信,在此之前,服務(wù)器都處于一個等待監(jiān)聽的狀態(tài)。監(jiān)聽本地端口這是一個極簡的,需要注意的是,我們僅實(shí)現(xiàn)了協(xié)議的部分。

基于 Python3 寫的極簡版 webserver。用于學(xué)習(xí) HTTP協(xié)議,及 WEB服務(wù)器 工作原理。筆者對 WEB服務(wù)器 的工作原理理解的比較粗淺,僅是基于個人的理解來寫的,存在很多不足和漏洞,目的在于給大家提供一個寫 webserver 的思路。項(xiàng)目GitHub地址:https://github.com/hanrenguang/simple-webserver。

WEB服務(wù)器原理

學(xué)過計網(wǎng)的同學(xué)應(yīng)該都知道 HTTP協(xié)議 是在 TCP協(xié)議 之上實(shí)現(xiàn)的。瀏覽器與服務(wù)器之間的通信首先是建立 TCP 連接,再進(jìn)行請求和響應(yīng)報文的傳輸。服務(wù)器是屬于被動的一方,當(dāng)瀏覽器發(fā)起請求的時候,服務(wù)器才能和瀏覽器通信,在此之前,服務(wù)器都處于一個等待監(jiān)聽的狀態(tài)。

socket連接

實(shí)現(xiàn)服務(wù)器的第一步是建立一個 socket 連接,socket 套接字是對 TCP/UDP協(xié)議 的一個封裝,Python 就自帶有 socket 模塊,所以使用起來很方便。

import socket

sk = socket.socket(
    socket.AF_INET, 
    socket.SOCK_STREAM
)

# 監(jiān)聽本地 8888 端口
host = "127.0.0.1"
port = 8888

sk.bind((host, port))
sk.listen(5)

while True:
    try:
        clientSk, addr = sk.accept()
        print("address is: %s" % str(addr))

        req = clientSk.recv(1024)

        clientSk.sendall("...")
        clientSk.close()

    except Exception as err:
        print(err)
        clientSk.close()

這是一個極簡的 socket-server,需要注意的是,我們僅實(shí)現(xiàn)了 TCP協(xié)議 的部分。

解析HTTP請求

拿到瀏覽器的請求很簡單,clientSk.recv() 即可獲取請求報文,而些數(shù)據(jù)我們無法直接拿來用,因?yàn)樗腔?HTTP協(xié)議 封裝的數(shù)據(jù),在我們進(jìn)行下一步操作前,需要對請求報文“解封”。而在此之前,我們需要了解請求報文的格式。最快捷的方式呢,是打開瀏覽器(以 chrome 為例),隨便打開百度啥的,F12 打開開發(fā)者工具,在 Network 一欄就可以觀察到。大概長下面這樣:

GET / HTTP/1.1
Host: xxx
Connection: xxx
Cache-Control: xxx
Upgrade-Insecure-Requests: xxx
User-Agent: xxx
Accept: xxx
Accept-Encoding: xxx
Accept-Language: xxx
Cookie: xxx

我們把關(guān)注點(diǎn)放在第一行,GET 方法,請求的資源路徑為 /,使用的協(xié)議是 HTTP1.1,之后就是一回車換行符 。所以我們對報文的解析如下(存在許多不足之處):

# 第一步先對數(shù)據(jù)進(jìn)行解碼 decode(),
# 再以行為單位進(jìn)行分割
requestList = clientSk.recv(1024).decode().split("
")

# 調(diào)用寫好的函數(shù)對其進(jìn)行解析
parseReq(requestList)

# 解析請求報文
def parseReq(reqList):
    # 保存解析結(jié)果
    parseRet = {}

    # 請求的方法,如 GET
    method = reqList[0].split(" ")[0]
    # 請求的資源路徑,如 "/"
    sourcePath = reqList[0].split(" ")[1]

    parseRet["method"] = method
    parseRet["sourcePath"] = sourcePath

    i = len(reqList) - 1

    # 以 key: value 的形式保存解析結(jié)果
    while i:
        if len(reqList[i].split(":")) == 1:
            i = i - 1
            continue

        idx = reqList[i].find(":")
        key, value = reqList[i][0:idx], reqList[i][idx+1:]
        parseRet[key] = value.strip()
        i = i - 1
    
    return parseRet
構(gòu)造響應(yīng)報文

拿到了請求報文并將其解析后,我們可以開始構(gòu)造響應(yīng)報文的內(nèi)容了,以請求靜態(tài)資源為例,假設(shè)請求報文第一行為 GET /index.html HTTP/1.1。那么我首先要做的就是先獲取路徑為 /index.html 的文件內(nèi)容:

# 獲取資源內(nèi)容
try:
    f = open(path, "r")
    while True:
        chunk = f.read(1024)
        if not chunk:
            f.close()
            break;
        content += chunk
except:
    pass

那接下來就是構(gòu)造響應(yīng)報文了,同理可以觀察 HTTP 響應(yīng)報文的格式,在此就不舉例了,直接上代碼:

try:
    f = open(path, "r")
    while True:
        chunk = f.read(1024)
        if not chunk:
            f.close()
            break;
        content += chunk
except:
    pass

# 省略了大部分頭部信息
headers = "HTTP/1.1 200 OK
"
contentType = "Content-Type: text/html; charset=utf-8
"
contentLen = "Content-Length: " + str(len(content)) + "
"

# 組合成響應(yīng)報文 res
res = headers + contentType + contentLen + "
" + content

# 編碼后發(fā)送給瀏覽器,
# 至此,本次通信結(jié)束
clientSk.sendall(res.encode(encoding="UTF-8"))
clientSk.close()
示例

到項(xiàng)目GitHub:https://github.com/hanrenguang/simple-webserver,下載本項(xiàng)目到本地,雙擊 server.py,并訪問 http://localhost:8888/index.html,你應(yīng)該會看到十分親切的 Hello world!。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/38625.html

相關(guān)文章

  • Oracle發(fā)布開源輕量級 Java 微服務(wù)框架 Helidon

    摘要:近日,推出了一個新的開源框架,該項(xiàng)目是一個用于創(chuàng)建基于微服務(wù)的應(yīng)用程序的庫集合。下圖說明了和所屬的微服務(wù)框架類別。啟用后,會將其跟蹤事件發(fā)送到。 近日,Oracle推出了一個新的開源框架Helidon,該項(xiàng)目是一個用于創(chuàng)建基于微服務(wù)的應(yīng)用程序的Java庫集合。和Payara Micro、Thorntail(之前的WildFly Swarm)、OpenLiberty、TomEE等項(xiàng)目一樣...

    Benedict Evans 評論0 收藏0
  • 淺析微服務(wù)框架 Helidon 使用

    摘要:零前期準(zhǔn)備版本版本核心依賴包支持包簡介是官方出品的微服務(wù)框架,底層基于驅(qū)動,大致的使用套路和相差不是很多筆者只是淺淺的了解過,可能存在理解不透的情況。一配置中的配置類有兩種,一種是用于讀取配置文件的,另一種是用于配置服務(wù)器對象的。 零 前期準(zhǔn)備 0 版本 JDK 版本 : OpenJDK 11.0.1 IDE : idea 2018.3 Helidon Webserver : heli...

    dockerclub 評論0 收藏0
  • 使用gulp配置代理,簡單解決前端跨域問題

    摘要:配置代理,解決跨域問題簡單的解決跨域問題,有實(shí)時重新加載功能,適用于偶爾改個文件,或者活動頁上面有簡單的前后端交互初始化全局安裝本地下載包下載包新建文件實(shí)時重新加載啟動時默認(rèn)瀏覽器打開的文件代理的域名因?yàn)樯壍搅?,所以? gulp配置代理,解決跨域問題 簡單的解決跨域問題,有實(shí)時重新加載功能,適用于偶爾改個文件,或者H5活動頁上面有簡單的前后端交互 npm init初始化 全局安裝gu...

    taohonghui 評論0 收藏0
  • 用gulp管理自己前端開發(fā)任務(wù)及需要注意

    摘要:但是頻繁的關(guān)閉服務(wù)與重啟服務(wù),這樣就造成了很多時間浪費(fèi),所以我們需要利用來監(jiān)視文件的改動,并將這些改動重新發(fā)布到生產(chǎn)目錄,并重啟服務(wù)非手動。三預(yù)處理器文件編譯暫時沒用到,后面用到再增加,可以參考其他人的 關(guān)于gulp,grunt,webpack,剛走前端模塊化的我,真的是傻傻分不清楚,幸好有大神各種答疑解惑,使我略知一二,你也想知道的,也許還想知道點(diǎn)啥,資源羅列:1、中文官方文檔;2、...

    gplane 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<