Python网络与多任务编程:TCP/UDP实战指南

发布于:2025-09-16 ⋅ 阅读:(18) ⋅ 点赞:(0)

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 socket

def tcp_client_send(host='127.0.0.1', port=8888):
    """TCP客户端发送数据"""
    # 创建TCP socket
    client_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 socket
    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:
                # 接收客户端数据
                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:
        # 关闭服务器socket
        server_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} 断开连接")
                        break
                    
                    print(f"收到来自 {client_address} 的消息: {data}")
                    
                    # 处理特殊命令
                    if data.lower() == 'exit':
                        response = "再见!"
                        client_socket.send(response.encode('utf-8'))
                        break
                    elif data.lower() == 'time':
                        from datetime import datetime
                        response = 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 threading

def 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} 断开连接")
                break
            
            print(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 = True
            client_thread.start()
            
    except KeyboardInterrupt:
        print("服务器被用户中断")
    finally:
        server_socket.close()
        print("服务器已关闭")

if __name__ == "__main__":
    tcp_server_multiple_clients()
1.2.4 TCP开发总结
  1. TCP特点:面向连接、可靠传输、流量控制、拥塞控制
  2. 适用场景:需要可靠数据传输的应用,如文件传输、邮件、Web浏览
  3. 开发要点
    • 客户端使用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 socket
    udp_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 socket
    udp_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 socket
    udp_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 sys
    if len(sys.argv) > 1 and sys.argv[1] == 'receiver':
        udp_broadcast_receiver()
    else:
        udp_broadcast_sender()

二、多任务编程

多任务编程允许程序同时执行多个任务,提高程序效率和响应性。Python中主要通过多线程和多进程实现。

2.1 多线程编程

import threading
import time

def 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 counter
    for _ 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 time

def cpu_intensive_task(n):
    """CPU密集型任务"""
    result = 0
    for i in range(n):
        result += i * i
    return result

if __name__ == "__main__":
    # 创建进程池
    with multiprocessing.Pool(processes=4) as pool:
        # 并行执行任务
        results = pool.map(cpu_intensive_task, [10000000] * 8)
        print(f"计算结果: {results}")

总结

本文介绍了Python网络编程和多任务编程的基础知识:

  1. 网络编程基础:IP地址、端口和编解码
  2. TCP编程:面向连接的可靠通信,适合需要数据完整性的场景
  3. UDP编程:无连接的快速通信,适合实时性要求高的场景
  4. 多任务编程:通过多线程和多进程提高程序效率

掌握这些知识后,你可以开发各种网络应用,从简单的客户端/服务器程序到复杂的分布式系统。在实际开发中,根据需求选择合适的协议和并发模型至关重要。