用 Python 進行網絡編程,就是在 Python 程序本身這個進程內,連接別的服務器進程的通信端口,進行通信。
TCP 編程
Socket 是網絡編程的一個抽象概念。通常我們用一個 Socket 表示“打開了一個網絡鏈接”,而打開一個 Socket 需要知道目標計算機的 IP 地址和端口號,再指定協議類型即可。
服務端
大多數連接都是可靠的 TCP 連接。創建 TCP 連接時,主動發起連接的叫客戶端,被動響應連接的叫服務器。
import socket
import threading
import time
def main():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 監聽端口:
s.bind(('127.0.0.1', 9999))
# 等待連接的最大數量
s.listen(5)
print('Waiting for connection...')
while True:
# 接受一個新連接:
sock, addr = s.accept()
# 創建新線程來處理TCP連接:
t = threading.Thread(target=tcpThread, args=(sock, addr))
t.start()
def tcpThread(sock, addr):
print('Accept new connection...')
sock.send('Welcome!'.encode('utf-8'))
while True:
data = sock.recv(1024)
time.sleep(1)
if not data or data.decode('utf-8') == 'exit':
break
print(data.decode('utf-8'))
sock.close()
main()
結果:
Waiting for connection...
Accept new connection...
你好,我是客戶端!
客戶端
創建 Socket 時,AF_INET 指定使用 IPv4 協議,如果要用更先進的 IPv6,就指定爲 AF_INET6。SOCK_STREAM 指定使用面向流的 TCP協議,這樣,一個 Socket 對象就創建成功。
def main():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 9999))
# 接收消息
print(s.recv(1024).decode('utf-8'))
s.send("你好,我是客戶端!".encode('utf-8'))
s.close()
main()
結果:Welcome!
UDP 編程
TCP 是建立可靠連接,並且通信雙方都可以以流的形式發送數據。相對TCP,UDP則是面向無連接的協議。使用 UDP 協議時,不需要建立連接,只需要知道對方的 IP 地址和端口號,就可以直接發數據包。但是,能不能到達就不知道了。
服務端
def main():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 綁定端口:
s.bind(('127.0.0.1', 9999))
print('Bind UDP on 9999...')
while True:
# 接收數據:
data, addr = s.recvfrom(1024)
print('Received from %s:%s.' % addr)
s.sendto(b'Hello, %s!' % data, addr)
main()
結果:
Bind UDP on 9999...
Received from 127.0.0.1:59333.
Received from 127.0.0.1:59333.
Received from 127.0.0.1:59333.
客戶端
def main():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
for data in [b'Michael', b'Tracy', b'Sarah']:
# 發送數據:
s.sendto(data, ('127.0.0.1', 9999))
# 接收數據:
print(s.recv(1024).decode('utf-8'))
s.close()
main()
結果:
Hello, Michael!
Hello, Tracy!
Hello, Sarah!
HTTP 編程
HTTP 是 HyperText Transfer Protocol 的縮寫,翻譯爲超文本傳輸協議,它是基於 TCP 協議之上的一種請求-響應協議。HTTP 請求的格式是固定的,它由 HTTP Header 和 HTTP Body 兩部分構成。
服務端
服務器端的 HTTP 編程本質上就是編寫 Web 服務器,這是一個非常複雜的體系,本次就不實現了。
客戶端
def main():
headers = {'Host': 'www.xxx.com'}
postdata = {'name': 'aaa'}
p = requests.post("https://baidu.com", data=postdata)
print(p.text)
main()
結果:頁面 html 信息。