簡單的HTTP服務器搭建

本文來自於千鋒教育在阿里雲開發者社區學習中心上線課程《Python入門2020最新大課》,主講人姜偉。

簡單的HTTP服務器搭建

HTTP協議:HyperText Transfer Protocol 超文本傳輸協議
協議的作用就是用來傳輸超文本 HTML(HyperTextMarkupLanguage)

HTML:超文本標記語言
HTTP:用來傳輸超文本的一個協議

以Chrome為例,在網頁空白處點擊右鍵,選擇檢查,就可以顯示開發者工具,其中:

  • Elements顯示網頁的結構
  • Network顯示瀏覽器和服務器的通信

點Network,確保第一個小紅燈亮著,Chrome就會記錄所有瀏覽器和服務器之間的通信:

image.png

General中包含了一些概覽信息,請求頭和響應頭在請求發送過程中的詳細過程如下:

image.png

import socket

# HTTP 服務器都是基於TCP的socket鏈接
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

server_socket.bind(('192.168.31.199', 9090))
server_socket.listen(128)

# 獲取的數據是一個元組,元組裡有兩個元素
# 第 0 個元素是 客戶端的socket鏈接
# 第 1 個元素是 客戶端的ip地址和端口號
client_socket, client_addr = server_socket.accept()

# 從客戶端的 socket 裡獲取數據
data = client_socket.recv(1024).decode('utf8')

# 給客戶端返回消息
client_socket.send('hello world'.encode('utf8'))
print(data)

在瀏覽器中訪問結果如下:

image.png

瀏覽器反饋bad response,說明需要先設置響應頭

import socket

# HTTP 服務器都是基於TCP的socket鏈接
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

server_socket.bind(('192.168.31.199', 9090))
server_socket.listen(128)

# 獲取的數據是一個元組,元組裡有兩個元素
# 第 0 個元素是 客戶端的socket鏈接
# 第 1 個元素是 客戶端的ip地址和端口號
client_socket, client_addr = server_socket.accept()

# 從客戶端的 socket 裡獲取數據
data = client_socket.recv(1024).decode('utf8')
print('接收到的數據{}'.format(data))

# 返回內容之前,需要先設置HTTP響應頭

# 設置一個響應頭就換一行
client_socket.send('HTTP/1.1 200 OK\n'.encode('utf8'))
client_socket.send('content-type:text/html\n'.encode('utf8'))

# 所有的響應頭設置完成以後,再換行
client_socket.send('\n'.encode('utf8'))

# 發送內容
client_socket.send('hello world'.encode('utf8'))

在瀏覽器中訪問結果如下:

image.png

將代碼中的地址改為0.0.0.0:

import socket

# HTTP 服務器都是基於TCP的socket鏈接
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

server_socket.bind(('0.0.0.0', 9090))
server_socket.listen(128)

# 獲取的數據是一個元組,元組裡有兩個元素
# 第 0 個元素是 客戶端的socket鏈接
# 第 1 個元素是 客戶端的ip地址和端口號
client_socket, client_addr = server_socket.accept()

# 從客戶端的 socket 裡獲取數據
data = client_socket.recv(1024).decode('utf8')
print('接收到{}的數據{}'.format(client_addr[0], data))

# 返回內容之前,需要先設置HTTP響應頭

# 設置一個響應頭就換一行
client_socket.send('HTTP/1.1 200 OK\n'.encode('utf8'))
client_socket.send('content-type:text/html\n'.encode('utf8'))

# 所有的響應頭設置完成以後,再換行
client_socket.send('\n'.encode('utf8'))

# 發送內容
client_socket.send('hello world'.encode('utf8'))

在雲服務器中運行此py文件,然後在瀏覽器中訪問服務器的地址的相應端口,訪問效果如下:

image.png

雲服務器中將打印出訪問頭和訪問者地址信息:

image.png

此時的代碼只能接收一次請求,可以在代碼中添加死循環,並將端口設置方式改為動態設置:

import socket

port = int(input('請輸入端口號:'))
# HTTP 服務器都是基於TCP的socket鏈接
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

server_socket.bind(('0.0.0.0', port))
server_socket.listen(128)
print('server is running at 0.0.0.0:{}'.format(port))

# 獲取的數據是一個元組,元組裡有兩個元素
# 第 0 個元素是 客戶端的socket鏈接
# 第 1 個元素是 客戶端的ip地址和端口號
while True:
    client_socket, client_addr = server_socket.accept()

    # 從客戶端的 socket 裡獲取數據
    data = client_socket.recv(1024).decode('utf8')
    print('接收到{}的數據{}'.format(client_addr[0], data))

    # 返回內容之前,需要先設置HTTP響應頭

    # 設置一個響應頭就換一行
    client_socket.send('HTTP/1.1 200 OK\n'.encode('utf8'))
    client_socket.send('content-type:text/html\n'.encode('utf8'))

    # 所有的響應頭設置完成以後,再換行
    client_socket.send('\n'.encode('utf8'))

    # 發送內容
    client_socket.send('hello world'.encode('utf8'))

在服務器中啟動,並使用8090端口:

image.png

瀏覽器中訪問結果:

image.png

調整返回的內容為訪問者的地址:

import socket

port = int(input('請輸入端口號:'))
# HTTP 服務器都是基於TCP的socket鏈接
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

server_socket.bind(('0.0.0.0', port))
server_socket.listen(128)
print('server is running at 0.0.0.0:{}'.format(port))

# 獲取的數據是一個元組,元組裡有兩個元素
# 第 0 個元素是 客戶端的socket鏈接
# 第 1 個元素是 客戶端的ip地址和端口號
while True:
    client_socket, client_addr = server_socket.accept()

    # 從客戶端的 socket 裡獲取數據
    data = client_socket.recv(1024).decode('utf8')
    print('接收到{}的數據{}'.format(client_addr[0], data))

    # 返回內容之前,需要先設置HTTP響應頭

    # 設置一個響應頭就換一行
    client_socket.send('HTTP/1.1 200 OK\n'.encode('utf8'))
    client_socket.send('content-type:text/html\n'.encode('utf8'))

    # 所有的響應頭設置完成以後,再換行
    client_socket.send('\n'.encode('utf8'))

    # 發送內容
    client_socket.send(client_addr[0].encode('utf8'))

瀏覽器訪問效果:

image.png

配套視頻

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top