一、最簡單的WEB頁面訪問過程

   互聯網應用都要經過通過OSI層封裝解封裝來達到遠程訪問效果。python中有寫好的socket模塊幫助開發人員實現這個功能,因此開發人員只要把注意力放在客戶端和服務端。對于WEB來說,客戶端就是瀏覽器,服務端則是提供頁面的程序所在的機器。客戶端已有成熟的各種瀏覽器,那么做出符合各種需求的頁面就比較關鍵。

  (1)首先模擬服務器程序

   一個簡單套import socket #導入socket模塊

sock = socket.socket()#實例化socket對象
sock.bind(('127.0.0.1',9000)) #綁定ip地址和端口號
sock.listen(5)  #設置監聽的客戶端數量
while True:
    conn, ddr = sock.accept()#conn是客戶端和服務端建立的鏈接,ddr是客戶端地址加端口號
    print(conn)#<socket.socket fd=440, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, 
  laddr=('127.0.0.1', 9000), raddr=('127.0.0.1', 57951)> print(ddr)#('127.0.0.1', 57951) data = conn.recv(1024) #接受客戶端訪問的數據 conn.send(b'HTTP/1.1 200 OK\r\n\r\nhello web') # 向客戶端發送數據,因為使用的瀏覽器,所以要加個HTTP標準格式,不然瀏覽器無法解析

 

  使用瀏覽器訪問:

  

  以上就是最基礎的WEB訪問過程,服務器返回的是一個二進制字符串數據,瀏覽器解析后變為正常的字符串顯示在頁面,而實際中則是要復雜得多。

  (2)使用html顯示頁面

    如果想構建復雜頁面,光靠一行行send二進制信息給瀏覽器解析是很不方便的。一方面不便于編寫,另一方面也不適合維護。所以通過寫html文件,然后利用open函數讀取htlm,再發送給瀏覽器解析則方便許多。

    代碼修改:

    

import socket #導入socket模塊
sock = socket.socket()#實例化socket對象
sock.bind(('127.0.0.1',9000)) #綁定ip地址和端口號
sock.listen(5)  #設置監聽的客戶端數量
while True:
    conn, ddr = sock.accept()#conn是客戶端和服務端建立的鏈接,ddr是客戶端地址加端口號
    data = conn.recv(1024)  # 接受客戶端訪問的數據
    with open('index.html','r') as f:
        data_html = f.read()
    conn.send(("HTTP/1.1 200 OK\r\n\r\n%s"%data_html).encode('utf-8')) # 向客戶端發送html文件的二進制信息

 

  這樣只要單獨編寫html文件,然后通過讀取文件方式再發送給瀏覽器,就可以方便的實現更復雜的頁面效果。

 (3)HTTP的請求和響應

  我們先看看上述最簡單的WEB訪問程序如何工作的。

  通過瀏覽器開發者選項下的Network可以看到:

  

 

  瀏覽器通過向服務器發送GET請求來獲得響應,實際是得到了服務器返回的html代碼然后解析成對應的頁面。下面簡單介紹HTTP請求過程。

  HTTP請求報文由三部分組成:請求行,請求頭和請求正文

  b'GET / HTTP/1.1\r\nHost: 127.0.0.1:9000\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0;   WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\n\r\n'

  請求行:指的是“GET / HTTP/1.1”,這種指明請求類型(有get或post)、URL路徑、HTTP協議和版本號的代碼行。

  請求頭:指的是由\r\n分割的代碼內容。里面包含了Host、Connection等信息。

  請求正文:指的是由\r\n\r\n分割的代碼內容。

  HTTP響應報文也有三部分構成:響應行,響應頭和實體內容  

  "HTTP/1.1 200 OK\r\nContent-Type:text/html\r\n\r\n%s"%data_html

  響應行:指的是
\r\n前面的HTTP協議及版本號和狀態碼。其中狀態碼有1XX、2XX、3XX、4XX、5XX等,通常1XX表示在正在處理接受的請求,2XX表示請求處理完畢、3XX表示重定向,
指的是服務器返回給瀏覽器需要重新訪問的頁面地址,相當于兩次HTTP請求過程。4XX通常表示客戶端請求錯誤指的是URL不正確等,5XX表示的是服務器處理請求出錯,為服務端程序錯誤。
  響應頭:指的是\r\n和\r\n\r\n中間的內容,在瀏覽器中可以看到:

  

  實體內容:指的是r\n\r\n之后的代碼,也是瀏覽器要解析的html代碼,通過它瀏覽器才能解析、渲染來向用戶提供頁面。