因爲網絡間通信是基於TCP協議傳輸數據的,而服務器與瀏覽器之間通信是基於HTTP協議的,那麼下面基於python實現一個tcp服務器,瀏覽器可以基於http協議進行發送請求和解析。展示瀏覽器返回一個固定頁面和HTML頁面案例。
1.服務器只能返回固定頁面給請求者
import socket
def handle_client(client_socket):
"爲一個客戶端進行服務"
recv_data = client_socket.recv(1024).decode("utf-8")
request_header_lines = recv_data.splitlines()
for line in request_header_lines:
print(line)
# 組織相應 頭信息(header)
response_headers = "HTTP/1.1 200 OK\r\n" # 200表示找到這個資源
response_headers += "\r\n" # 用一個空的行與body進行隔開
# 組織 內容(body)
response_body = "hello world"
response = response_headers + response_body
client_socket.send(response.encode("utf-8"))
client_socket.close()
def main():
"作爲程序的主控制入口"
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 設置當服務器先close 即服務器端4次揮手之後資源能夠立即釋放,這樣就保證了,下次運行程序時 可以立即綁定7788端口
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind(("", 7788))
server_socket.listen(128)
while True:
client_socket, client_addr = server_socket.accept()
handle_client(client_socket)
if __name__ == "__main__":
main()
使用“網路調試助手"作爲TCP 客戶端發送請求給服務器,服務器將固定返回基於http協議格式的hello,world給所有的請求者。
使用瀏覽器基於HTTP協議訪問該服務器如下,服務器將固定返回基於http協議格式的hello,world給所有的請求者。這裏因爲瀏覽器可以解析http協議的格式文件,所以可以通過網頁的形式展示出來hello,world。當然如果瀏覽器返回一個完整的網頁,那麼同樣瀏覽器也可以解析整個網頁,這就是我們日常使用的服務器與瀏覽器基於http協議的通信啦。
2.服務器返回一個網頁頁面給請求者
瀏覽器通過http協議請求該TCP服務器,該服務器返回一個網頁頁面給瀏覽器,瀏覽器解析以後顯示到前端。
import socket
def service_client(new_socket):
"""爲這個客戶端返回數據"""
# 1. 接收瀏覽器發送過來的請求 ,即http請求
# GET / HTTP/1.1
# .....
request = new_socket.recv(1024)
print(">>>" * 50)
print(request)
# 2. 返回http格式的數據,給瀏覽器
# 2.1 準備發送給瀏覽器的數據---header
response = "HTTP/1.1 200 OK\r\n"
response += "\r\n"
# 2.2 準備發送給瀏覽器的數據---boy
# response += "hahahhah"
f = open("./html/index.html", "rb") #讀取的這個文件是我們提前放在程序當前目錄下的,用來測試的文件。
html_content = f.read()
f.close()
# 將response header發送給瀏覽器
new_socket.send(response.encode("utf-8"))
# 將response body發送給瀏覽器
new_socket.send(html_content) #注意這裏send的數據沒有encode,文件open的方式就是rb,二進制格式
# 關閉套接
new_socket.close()
def main():
"""用來完成整體的控制"""
# 1. 創建套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 設置當服務器先close 即服務器端4次揮手之後資源能夠立即釋放,這樣就保證了,下次運行程序時 可以立即綁定7890端口
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 2. 綁定
tcp_server_socket.bind(("", 7890))
# 3. 變爲監聽套接字
tcp_server_socket.listen(128)
while True:
# 4. 等待新客戶端的鏈接
new_socket, client_addr = tcp_server_socket.accept()
# 5. 爲這個客戶端服務
service_client(new_socket)
# 關閉監聽套接字
tcp_server_socket.close()
if __name__ == "__main__":
main()
使用瀏覽器訪問服務器,因爲這裏我定義的是服務器固定返回一個網頁(這個網頁使我們提前放在服務器上的。),所以只要你訪問的是這個服務器,這個端口 ,所有的返回都是一樣。 所以,你訪問的網址,可以任意定義,都不會影響這個訪問結果,比如http://127.0.0.1:7890/dfsdf/aaaa,http://127.0.0.1:7890/aaa/index 等結果都是一樣的。
如下服務器端顯示了瀏覽器的get請求,但是注意,實際我們訪問一次,但是服務器顯示瀏覽器發送了多次get請求,這是爲什麼呢?
尖叫提示:當瀏覽器讀取到index首頁的HTML源碼後,它會解析HTML,顯示頁面,然後,根據HTML裏面的各種鏈接,再發送HTTP請求給新浪服務器,拿到相應的圖片、視頻、Flash、JavaScript腳本、CSS等各種資源,最終顯示出一個完整的頁面。所以我們在下面能看到很多額外的HTTP請求。
D:\software\python3\python.exe D:/pythoyworkspace/file_demo/Class_Demo/pachong/urllib_Request_Post.py
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
b'GET / HTTP/1.1\r\nHost: 127.0.0.1:7890\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; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 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'
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
b'GET /classic.css HTTP/1.1\r\nHost: 127.0.0.1:7890\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36\r\nAccept: text/css,*/*;q=0.1\r\nReferer: http://127.0.0.1:7890/\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\n\r\n'
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
b'GET /images/qt-logo.png HTTP/1.1\r\nHost: 127.0.0.1:7890\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36\r\nAccept: image/webp,image/apng,image/*,*/*;q=0.8\r\nReferer: http://127.0.0.1:7890/\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\n\r\n'
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
b'GET /images/trolltech-logo.png HTTP/1.1\r\nHost: 127.0.0.1:7890\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36\r\nAccept: image/webp,image/apng,image/*,*/*;q=0.8\r\nReferer: http://127.0.0.1:7890/\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\n\r\n'
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
b'GET /favicon.ico HTTP/1.1\r\nHost: 127.0.0.1:7890\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36\r\nAccept: image/webp,image/apng,image/*,*/*;q=0.8\r\nReferer: http://127.0.0.1:7890/\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\n\r\n'