HTTP\socket\TCP
請參考網絡模型,計算機給我們提供了socket,通過socket可以直接與傳輸層打交道
Socket編程的模式
client和server實現通信
首先是服務端
import socket
# 指明爲ipv4與tcp協議
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 必須傳入元組
server.bind(("0.0.0.0", 8000))
# 實現監聽
server.listen()
sock, addr = server.accept()
# 獲取從客戶端發送的數據,每次獲取1k的數據
data = sock.recv(1024)
# 將字節流轉碼爲utf-8編碼
print(data.decode("utf-8"))
sock.close()
server.close()
接着是客戶端
import socket
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(("127.0.0.1", 8000))
# 以字節輸出
client.send("Y4tacker".encode("utf-8"))
client.close()
這樣就實現了
socket實現聊天和多用戶連接
實現聊天
取消close方法即可,再加個while循環
服務端
while True:
data = sock.recv(1024).decode("utf-8")
print(data)
ret_data = input("輸入回覆:")
sock.send(ret_data.encode("utf-8"))
客戶端
while True:
data = client.recv(1024)
print(data.decode("utf-8"))
ret_data = input("輸入回覆:")
client.send(ret_data.encode("utf-8"))
利用線程實現多用戶的連接
服務端
import socket
import threading
# 指明爲ipv4與tcp協議
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 必須傳入元組
server.bind(("0.0.0.0", 8000))
# 實現監聽
server.listen()
def handle_sock(sock, addr):
while True:
data = sock.recv(1024).decode("utf-8")
print(data)
if "exit" == data:
break
ret_data = input()
sock.send(ret_data.encode("utf-8"))
sock.close()
print("關閉連接")
while True:
sock, addr = server.accept()
# 用線程處理新的用戶連接
client_thread = threading.Thread(target=handle_sock, args=(sock, addr))
client_thread.start()
客戶端
import socket
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(("127.0.0.1", 8000))
while True:
ret_data = input()
client.send(ret_data.encode("utf-8"))
data = client.recv(1024)
print(data.decode("utf-8"))
if "exit" == ret_data:
print("關閉連接")
break
client.close()
socket模擬http請求
爲了方便,利用urlparse來解析url
import socket
from urllib.parse import urlparse
def get_url(url):
url = urlparse(url)
# 以http://www.baidu.com/aa.html爲例
# ParseResult(scheme='http', netloc='www.baidu.com', path='/aa.html', params='', query='', fragment='')
host = url.netloc
path = url.path
if path == "":
path = "/"
# 建立socket連接
con = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# HTTP都是80端口
con.connect((host, 80))
# 發送請求
con.send(f'GET {path} HTTP/1.1\r\nHost:{host}\r\nConnection:close\r\n\r\n'.encode("utf-8"))
# 接收請求,如果數據大於1024字節,則通過多次接收
data = b""
while True:
temp = con.recv(1024)
if temp:
data += temp
else:
break
data = data.decode("utf-8")
# 去除請求頭
html_data = data.split("\r\n\r\n")[1]
print(html_data)
con.close()
if __name__ == '__main__':
url = "http://www.baidu.com"
get_url(url)