Python網絡與多任務編程:TCP/UDP實戰指南
一、網絡編程
1.1 前言
網絡編程是現代軟件開發中不可或缺的一部分,它使得不同設備之間的數據交換成為可能。Python提供了強大的標準庫來支持各種網絡編程需求。
1.1.1 IP地址簡介
IP地址是互聯網上設備的唯一標識符,分為IPv4和IPv6兩種格式:
import socket# 獲取本機IP地址
hostname = socket.gethostname()
ip_address = socket.gethostbyname(hostname)
print(f"主機名: {hostname}")
print(f"IP地址: {ip_address}")# 域名解析
domain = "www.google.com"
try:ip = socket.gethostbyname(domain)print(f"{domain} 的IP地址是: {ip}")
except socket.gaierror:print(f"無法解析域名: {domain}")
1.1.2 端口和端口號簡介
端口是網絡通信的端點,端口號范圍是0-65535,其中0-1023為知名端口,一般由系統服務使用。
# 常見端口號示例
common_ports = {"HTTP": 80,"HTTPS": 443,"FTP": 21,"SSH": 22,"SMTP": 25,"DNS": 53
}print("常見服務端口號:")
for service, port in common_ports.items():print(f"{service}: {port}")
1.1.3 字符串數據編解碼
網絡傳輸中數據需要以字節形式傳輸,因此需要進行編解碼操作:
# 字符串編碼與解碼
text = "你好,世界!"# 編碼為字節
encoded_data = text.encode('utf-8')
print(f"編碼后: {encoded_data}")# 解碼為字符串
decoded_text = encoded_data.decode('utf-8')
print(f"解碼后: {decoded_text}")# 其他編碼方式
text_gbk = text.encode('gbk')
print(f"GBK編碼: {text_gbk}")
1.2 TCP
1.2.1 TCP介紹
TCP(傳輸控制協議)是一種面向連接的、可靠的、基于字節流的傳輸層通信協議。它提供全雙工通信,確保數據順序傳輸且不丟失。
1.2.2 TCP客戶端開發
1.2.2.1 發送數據
import socketdef tcp_client_send(host='127.0.0.1', port=8888):"""TCP客戶端發送數據"""# 創建TCP socketclient_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)try:# 連接服務器client_socket.connect((host, port))print(f"已連接到服務器 {host}:{port}")# 發送數據message = "Hello, TCP Server!"client_socket.send(message.encode('utf-8'))print(f"已發送: {message}")except Exception as e:print(f"連接錯誤: {e}")finally:# 關閉連接client_socket.close()print("連接已關閉")if __name__ == "__main__":tcp_client_send()
1.2.2.2 發送并接收數據
def tcp_client_send_receive(host='127.0.0.1', port=8888):"""TCP客戶端發送并接收數據"""client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)try:client_socket.connect((host, port))print(f"已連接到服務器 {host}:{port}")# 發送數據message = "Hello, Server! How are you?"client_socket.send(message.encode('utf-8'))print(f"已發送: {message}")# 接收響應response = client_socket.recv(1024).decode('utf-8')print(f"收到響應: {response}")except Exception as e:print(f"錯誤: {e}")finally:client_socket.close()print("連接已關閉")if __name__ == "__main__":tcp_client_send_receive()
1.2.3 TCP服務器開發
1.2.3.1 接收客戶端消息并回復
def tcp_server_simple(host='127.0.0.1', port=8888):"""簡單的TCP服務器,接收消息并回復"""# 創建TCP socketserver_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 設置地址重用server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)# 綁定地址和端口server_socket.bind((host, port))# 開始監聽,設置最大連接數server_socket.listen(5)print(f"服務器啟動,監聽 {host}:{port}")try:while True:# 接受客戶端連接client_socket, client_address = server_socket.accept()print(f"接收到來自 {client_address} 的連接")try:# 接收客戶端數據data = client_socket.recv(1024).decode('utf-8')if data:print(f"收到消息: {data}")# 回復客戶端response = f"服務器已收到你的消息: {data}"client_socket.send(response.encode('utf-8'))except Exception as e:print(f"處理客戶端數據時出錯: {e}")finally:# 關閉客戶端連接client_socket.close()print(f"與 {client_address} 的連接已關閉")except KeyboardInterrupt:print("服務器被用戶中斷")finally:# 關閉服務器socketserver_socket.close()print("服務器已關閉")if __name__ == "__main__":tcp_server_simple()
1.2.3.2 接收客戶端的多條信息
def tcp_server_multiple_messages(host='127.0.0.1', port=8888):"""處理客戶端多條消息的TCP服務器"""server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)server_socket.bind((host, port))server_socket.listen(5)print(f"服務器啟動,監聽 {host}:{port}")try:while True:client_socket, client_address = server_socket.accept()print(f"接收到來自 {client_address} 的連接")try:# 持續接收客戶端消息while True:data = client_socket.recv(1024).decode('utf-8')if not data:print(f"{client_address} 斷開連接")breakprint(f"收到來自 {client_address} 的消息: {data}")# 處理特殊命令if data.lower() == 'exit':response = "再見!"client_socket.send(response.encode('utf-8'))breakelif data.lower() == 'time':from datetime import datetimeresponse = f"當前時間: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"client_socket.send(response.encode('utf-8'))else:response = f"已收到: {data}"client_socket.send(response.encode('utf-8'))except ConnectionResetError:print(f"{client_address} 異常斷開連接")except Exception as e:print(f"處理 {client_address} 時出錯: {e}")finally:client_socket.close()except KeyboardInterrupt:print("服務器被用戶中斷")finally:server_socket.close()print("服務器已關閉")if __name__ == "__main__":tcp_server_multiple_messages()
1.2.3.3 允許客戶端多次連接
import threadingdef handle_client(client_socket, client_address):"""處理客戶端連接的線程函數"""print(f"開始處理 {client_address} 的連接")try:while True:data = client_socket.recv(1024).decode('utf-8')if not data:print(f"{client_address} 斷開連接")breakprint(f"收到來自 {client_address} 的消息: {data}")# 回復客戶端response = f"服務器已收到: {data}"client_socket.send(response.encode('utf-8'))except ConnectionResetError:print(f"{client_address} 異常斷開連接")except Exception as e:print(f"處理 {client_address} 時出錯: {e}")finally:client_socket.close()print(f"{client_address} 的連接已關閉")def tcp_server_multiple_clients(host='127.0.0.1', port=8888):"""支持多客戶端連接的TCP服務器"""server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)server_socket.bind((host, port))server_socket.listen(5)print(f"服務器啟動,監聽 {host}:{port}")try:while True:client_socket, client_address = server_socket.accept()print(f"接收到來自 {client_address} 的連接")# 為每個客戶端創建新線程client_thread = threading.Thread(target=handle_client, args=(client_socket, client_address))client_thread.daemon = Trueclient_thread.start()except KeyboardInterrupt:print("服務器被用戶中斷")finally:server_socket.close()print("服務器已關閉")if __name__ == "__main__":tcp_server_multiple_clients()
1.2.4 TCP開發總結
- TCP特點:面向連接、可靠傳輸、流量控制、擁塞控制
- 適用場景:需要可靠數據傳輸的應用,如文件傳輸、郵件、Web瀏覽
- 開發要點:
- 客戶端使用connect()連接服務器
- 服務器使用bind()綁定地址,listen()監聽,accept()接受連接
- 使用send()和recv()進行數據傳輸
- 及時關閉連接釋放資源
- 處理異常和連接中斷情況
1.3 UDP
1.3.1 UDP介紹
UDP(用戶數據報協議)是一種無連接的傳輸層協議,提供不可靠的數據報服務。它不保證數據順序和可靠性,但傳輸效率高。
1.3.2 UDP發送端開發
def udp_sender(host='127.0.0.1', port=9999):"""UDP發送端"""# 創建UDP socketudp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)try:while True:# 獲取用戶輸入message = input("請輸入要發送的消息 (輸入 'exit' 退出): ")if message.lower() == 'exit':break# 發送數據udp_socket.sendto(message.encode('utf-8'), (host, port))print(f"已發送到 {host}:{port}: {message}")except Exception as e:print(f"發送錯誤: {e}")finally:udp_socket.close()print("UDP發送端已關閉")if __name__ == "__main__":udp_sender()
1.3.3 UDP接收端開發
def udp_receiver(host='127.0.0.1', port=9999):"""UDP接收端"""# 創建UDP socketudp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)# 綁定地址和端口udp_socket.bind((host, port))print(f"UDP接收端啟動,監聽 {host}:{port}")try:while True:# 接收數據data, addr = udp_socket.recvfrom(1024)message = data.decode('utf-8')print(f"收到來自 {addr} 的消息: {message}")# 可選:發送回復if message.lower() == 'hello':reply = "Hello from UDP Receiver!"udp_socket.sendto(reply.encode('utf-8'), addr)except KeyboardInterrupt:print("接收端被用戶中斷")except Exception as e:print(f"接收錯誤: {e}")finally:udp_socket.close()print("UDP接收端已關閉")if __name__ == "__main__":udp_receiver()
1.3.4 UDP廣播
def udp_broadcast_sender(port=9999):"""UDP廣播發送端"""# 創建UDP socketudp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)# 設置廣播選項udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)# 廣播地址broadcast_address = '<broadcast>'try:while True:# 獲取用戶輸入message = input("請輸入廣播消息 (輸入 'exit' 退出): ")if message.lower() == 'exit':break# 發送廣播udp_socket.sendto(message.encode('utf-8'), (broadcast_address, port))print(f"已廣播: {message}")except Exception as e:print(f"廣播錯誤: {e}")finally:udp_socket.close()print("廣播發送端已關閉")def udp_broadcast_receiver(port=9999):"""UDP廣播接收端"""udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)# 綁定到所有接口udp_socket.bind(('', port))print(f"廣播接收端啟動,監聽端口 {port}")try:while True:data, addr = udp_socket.recvfrom(1024)message = data.decode('utf-8')print(f"收到來自 {addr} 的廣播: {message}")except KeyboardInterrupt:print("廣播接收端被用戶中斷")except Exception as e:print(f"接收錯誤: {e}")finally:udp_socket.close()print("廣播接收端已關閉")if __name__ == "__main__":# 需要在不同終端運行接收端和發送端import sysif len(sys.argv) > 1 and sys.argv[1] == 'receiver':udp_broadcast_receiver()else:udp_broadcast_sender()
二、多任務編程
多任務編程允許程序同時執行多個任務,提高程序效率和響應性。Python中主要通過多線程和多進程實現。
2.1 多線程編程
import threading
import timedef worker(name, delay):"""簡單的 worker 函數"""print(f"線程 {name} 開始執行")time.sleep(delay)print(f"線程 {name} 執行完成,延遲 {delay} 秒")# 創建多個線程
threads = []
for i in range(5):t = threading.Thread(target=worker, args=(f"Thread-{i}", i))threads.append(t)t.start()# 等待所有線程完成
for t in threads:t.join()print("所有線程執行完成")
2.2 線程同步
import threading# 使用鎖進行同步
counter = 0
lock = threading.Lock()def increment_counter():global counterfor _ in range(100000):with lock: # 使用上下文管理器自動獲取和釋放鎖counter += 1# 創建多個線程增加計數器
threads = []
for _ in range(10):t = threading.Thread(target=increment_counter)threads.append(t)t.start()for t in threads:t.join()print(f"最終計數器值: {counter} (應為 1000000)")
2.3 多進程編程
import multiprocessing
import timedef cpu_intensive_task(n):"""CPU密集型任務"""result = 0for i in range(n):result += i * ireturn resultif __name__ == "__main__":# 創建進程池with multiprocessing.Pool(processes=4) as pool:# 并行執行任務results = pool.map(cpu_intensive_task, [10000000] * 8)print(f"計算結果: {results}")
總結
本文介紹了Python網絡編程和多任務編程的基礎知識:
- 網絡編程基礎:IP地址、端口和編解碼
- TCP編程:面向連接的可靠通信,適合需要數據完整性的場景
- UDP編程:無連接的快速通信,適合實時性要求高的場景
- 多任務編程:通過多線程和多進程提高程序效率
掌握這些知識后,你可以開發各種網絡應用,從簡單的客戶端/服務器程序到復雜的分布式系統。在實際開發中,根據需求選擇合適的協議和并發模型至關重要。