一Python socket 模块详解socket 模块提供了对 Berkeley sockets API 的访问是实现网络通信的基础。通过它可以创建客户端和服务器进行 TCP 或 UDP 数据传输。1. 核心概念1地址族Address Family指定通信使用的协议。AF_INETIPv4最常用AF_INET6IPv6AF_UNIXUnix 域套接字本地进程间通信2套接字类型Socket TypeSOCK_STREAM面向连接的可靠字节流TCPSOCK_DGRAM无连接的数据报UDPSOCK_RAW原始套接字通常需要管理员权限3协议Protocol通常设为 0让系统自动选择。2. 主要函数与方法1创建 socketimport socket s socket.socket(familysocket.AF_INET, typesocket.SOCK_STREAM, proto0)family默认为AF_INETtype默认为SOCK_STREAM。2服务器端常用方法bind(address)将套接字绑定到指定地址IP 和端口。address格式(host, port)例如(127.0.0.1, 8888)。listen([backlog])开始监听连接请求。backlog 指定最大挂起连接数。accept()阻塞等待客户端连接返回(conn, address)其中conn是新的套接字对象用于与客户端通信。3客户端常用方法connect(address)连接到远程服务器。connect_ex(address)类似connect()但返回错误码而不是抛出异常。4数据收发send(bytes)发送数据返回实际发送的字节数可能小于数据长度。可使用sendall()确保全部发送。recv(bufsize[, flags])接收数据最多bufsize字节返回接收到的字节串。sendto(bytes, address)UDP 发送数据到指定地址。recvfrom(bufsize)UDP 接收数据返回(data, address)。5控制选项setsockopt(level, optname, value) / getsockopt(level, optname)设置/获取套接字选项。例如socket.SO_REUSEADDR允许重用地址。setblocking(flag)设置阻塞模式。flagFalse时套接字为非阻塞若操作无法立即完成则抛出BlockingIOError。settimeout(value)设置超时时间秒。超时后操作抛出timeout异常。6关闭套接字close()释放资源。7辅助函数gethostname()获取本地主机名。gethostbyname(hostname)将主机名解析为 IPv4 地址。gethostbyaddr(ip_address)反向解析。getaddrinfo(host, port, family0, type0, proto0, flags0)获取地址信息列表是编写协议无关代码的推荐方式。3. 使用示例1TCP 服务器具体示例如下import socket server socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 允许端口重用 server.bind((0.0.0.0, 8888)) server.listen(5) print(Server listening on port 8888) while True: conn, addr server.accept() print(fConnected by {addr}) data conn.recv(1024) if data: conn.sendall(bReceived: data) conn.close()2TCP 客户端具体示例如下import socket client socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect((127.0.0.1, 8888)) client.sendall(bHello, server!) response client.recv(1024) print(Received:, response) client.close()3UDP 服务器import socket udp_server socket.socket(socket.AF_INET, socket.SOCK_DGRAM) udp_server.bind((0.0.0.0, 8889)) while True: data, addr udp_server.recvfrom(1024) print(fMessage from {addr}: {data}) udp_server.sendto(bACK, addr)4. 注意事项异常处理网络操作可能引发socket.error、timeout等异常应使用try/except捕获。阻塞与非阻塞默认情况下accept()、recv()等会阻塞线程可使用setblocking(False)或settimeout()改变行为。字节与字符串网络传输的是字节数据发送前需将字符串编码如encode()接收后解码decode()。二Python threading 模块详解threading 模块提供了高级的多线程编程接口允许在单个进程中并发执行多个任务。1. 核心概念1线程Thread轻量级进程共享进程的内存空间。2全局解释器锁GILCPython 中GIL 使得同一时刻只有一个线程执行 Python 字节码因此多线程并不能充分利用多核 CPU 进行并行计算但在 I/O 密集型任务中依然有效。3线程安全多个线程同时访问共享数据时需要同步机制避免数据竞争。2. 主要类与函数1Thread 类创建线程t threading.Thread(targetfunc, args(arg1,), kwargs{}, nameThread-1)其中target线程执行的函数。args位置参数元组。kwargs关键字参数字典。name线程名称。启动线程t.start()等待线程结束t.join(timeout)阻塞直到线程终止。其他属性t.ident线程标识符、t.is_alive()是否存活、t.daemon是否为守护线程。2线程同步原语Lock互斥锁。acquire(blockingTrue, timeout-1)获取锁可阻塞。release()释放锁。示例lock threading.Lock() lock.acquire() # 临界区 lock.release()更推荐使用with lock: 上下文管理器。RLock可重入锁同一线程可多次获取避免死锁。Semaphore信号量允许一定数量的线程同时访问资源。Event事件用于线程间通信。set()、wait()、clear()。Condition条件变量可用于生产者-消费者模式。线程间通信queue.Queue线程安全的队列常用于数据交换。put(item)入队。get()出队若队列空则阻塞。3模块级函数threading.active_count()当前存活的线程数。threading.current_thread()返回当前线程对象。threading.enumerate()返回所有存活线程的列表。threading.main_thread()返回主线程对象。3. 使用示例1创建并启动线程import threading import time def worker(name): print(fThread {name} starting) time.sleep(2) print(fThread {name} finished) threads [] for i in range(3): t threading.Thread(targetworker, args(i,)) t.start() threads.append(t) for t in threads: t.join() print(All threads done)2使用锁避免竞争条件import threading counter 0 lock threading.Lock() def increment(): global counter for _ in range(100000): with lock: counter 1 threads [threading.Thread(targetincrement) for _ in range(2)] for t in threads: t.start() for t in threads: t.join() print(counter) # 正确输出 2000003使用 Queue 进行线程间通信生产者-消费者import threading import queue import time def producer(q): for i in range(5): item fitem-{i} q.put(item) print(fProduced {item}) time.sleep(1) q.put(None) # 结束信号 def consumer(q): while True: item q.get() if item is None: break print(fConsumed {item}) time.sleep(1.5) q queue.Queue() t1 threading.Thread(targetproducer, args(q,)) t2 threading.Thread(targetconsumer, args(q,)) t1.start() t2.start() t1.join() t2.join()4. 注意事项守护线程Daemon Thread设置t.daemon True或在构造时指定主线程退出时守护线程会自动终止不会等待。避免死锁多个锁嵌套使用时确保获取顺序一致或使用RLock。线程安全不要共享可变对象而不加锁使用Queue或threading 同步原语。GIL 的影响对于 CPU 密集型任务多线程可能比单线程还慢可考虑multiprocessing模块。三socket 和 threading 结合使用socket 和 threading 常结合使用例如在多线程服务器中每个客户端连接分配一个线程处理。典型模式import socket import threading def handle_client(conn, addr): with conn: print(fThread {threading.current_thread().name} handling {addr}) while True: data conn.recv(1024) if not data: break conn.sendall(data) server socket.socket() server.bind((0.0.0.0, 8888)) server.listen(5) while True: conn, addr server.accept() t threading.Thread(targethandle_client, args(conn, addr)) t.start()这样每个连接独立处理主线程继续等待新连接。
Python模块详解(一)—— socket 和 threading 模块
一Python socket 模块详解socket 模块提供了对 Berkeley sockets API 的访问是实现网络通信的基础。通过它可以创建客户端和服务器进行 TCP 或 UDP 数据传输。1. 核心概念1地址族Address Family指定通信使用的协议。AF_INETIPv4最常用AF_INET6IPv6AF_UNIXUnix 域套接字本地进程间通信2套接字类型Socket TypeSOCK_STREAM面向连接的可靠字节流TCPSOCK_DGRAM无连接的数据报UDPSOCK_RAW原始套接字通常需要管理员权限3协议Protocol通常设为 0让系统自动选择。2. 主要函数与方法1创建 socketimport socket s socket.socket(familysocket.AF_INET, typesocket.SOCK_STREAM, proto0)family默认为AF_INETtype默认为SOCK_STREAM。2服务器端常用方法bind(address)将套接字绑定到指定地址IP 和端口。address格式(host, port)例如(127.0.0.1, 8888)。listen([backlog])开始监听连接请求。backlog 指定最大挂起连接数。accept()阻塞等待客户端连接返回(conn, address)其中conn是新的套接字对象用于与客户端通信。3客户端常用方法connect(address)连接到远程服务器。connect_ex(address)类似connect()但返回错误码而不是抛出异常。4数据收发send(bytes)发送数据返回实际发送的字节数可能小于数据长度。可使用sendall()确保全部发送。recv(bufsize[, flags])接收数据最多bufsize字节返回接收到的字节串。sendto(bytes, address)UDP 发送数据到指定地址。recvfrom(bufsize)UDP 接收数据返回(data, address)。5控制选项setsockopt(level, optname, value) / getsockopt(level, optname)设置/获取套接字选项。例如socket.SO_REUSEADDR允许重用地址。setblocking(flag)设置阻塞模式。flagFalse时套接字为非阻塞若操作无法立即完成则抛出BlockingIOError。settimeout(value)设置超时时间秒。超时后操作抛出timeout异常。6关闭套接字close()释放资源。7辅助函数gethostname()获取本地主机名。gethostbyname(hostname)将主机名解析为 IPv4 地址。gethostbyaddr(ip_address)反向解析。getaddrinfo(host, port, family0, type0, proto0, flags0)获取地址信息列表是编写协议无关代码的推荐方式。3. 使用示例1TCP 服务器具体示例如下import socket server socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 允许端口重用 server.bind((0.0.0.0, 8888)) server.listen(5) print(Server listening on port 8888) while True: conn, addr server.accept() print(fConnected by {addr}) data conn.recv(1024) if data: conn.sendall(bReceived: data) conn.close()2TCP 客户端具体示例如下import socket client socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect((127.0.0.1, 8888)) client.sendall(bHello, server!) response client.recv(1024) print(Received:, response) client.close()3UDP 服务器import socket udp_server socket.socket(socket.AF_INET, socket.SOCK_DGRAM) udp_server.bind((0.0.0.0, 8889)) while True: data, addr udp_server.recvfrom(1024) print(fMessage from {addr}: {data}) udp_server.sendto(bACK, addr)4. 注意事项异常处理网络操作可能引发socket.error、timeout等异常应使用try/except捕获。阻塞与非阻塞默认情况下accept()、recv()等会阻塞线程可使用setblocking(False)或settimeout()改变行为。字节与字符串网络传输的是字节数据发送前需将字符串编码如encode()接收后解码decode()。二Python threading 模块详解threading 模块提供了高级的多线程编程接口允许在单个进程中并发执行多个任务。1. 核心概念1线程Thread轻量级进程共享进程的内存空间。2全局解释器锁GILCPython 中GIL 使得同一时刻只有一个线程执行 Python 字节码因此多线程并不能充分利用多核 CPU 进行并行计算但在 I/O 密集型任务中依然有效。3线程安全多个线程同时访问共享数据时需要同步机制避免数据竞争。2. 主要类与函数1Thread 类创建线程t threading.Thread(targetfunc, args(arg1,), kwargs{}, nameThread-1)其中target线程执行的函数。args位置参数元组。kwargs关键字参数字典。name线程名称。启动线程t.start()等待线程结束t.join(timeout)阻塞直到线程终止。其他属性t.ident线程标识符、t.is_alive()是否存活、t.daemon是否为守护线程。2线程同步原语Lock互斥锁。acquire(blockingTrue, timeout-1)获取锁可阻塞。release()释放锁。示例lock threading.Lock() lock.acquire() # 临界区 lock.release()更推荐使用with lock: 上下文管理器。RLock可重入锁同一线程可多次获取避免死锁。Semaphore信号量允许一定数量的线程同时访问资源。Event事件用于线程间通信。set()、wait()、clear()。Condition条件变量可用于生产者-消费者模式。线程间通信queue.Queue线程安全的队列常用于数据交换。put(item)入队。get()出队若队列空则阻塞。3模块级函数threading.active_count()当前存活的线程数。threading.current_thread()返回当前线程对象。threading.enumerate()返回所有存活线程的列表。threading.main_thread()返回主线程对象。3. 使用示例1创建并启动线程import threading import time def worker(name): print(fThread {name} starting) time.sleep(2) print(fThread {name} finished) threads [] for i in range(3): t threading.Thread(targetworker, args(i,)) t.start() threads.append(t) for t in threads: t.join() print(All threads done)2使用锁避免竞争条件import threading counter 0 lock threading.Lock() def increment(): global counter for _ in range(100000): with lock: counter 1 threads [threading.Thread(targetincrement) for _ in range(2)] for t in threads: t.start() for t in threads: t.join() print(counter) # 正确输出 2000003使用 Queue 进行线程间通信生产者-消费者import threading import queue import time def producer(q): for i in range(5): item fitem-{i} q.put(item) print(fProduced {item}) time.sleep(1) q.put(None) # 结束信号 def consumer(q): while True: item q.get() if item is None: break print(fConsumed {item}) time.sleep(1.5) q queue.Queue() t1 threading.Thread(targetproducer, args(q,)) t2 threading.Thread(targetconsumer, args(q,)) t1.start() t2.start() t1.join() t2.join()4. 注意事项守护线程Daemon Thread设置t.daemon True或在构造时指定主线程退出时守护线程会自动终止不会等待。避免死锁多个锁嵌套使用时确保获取顺序一致或使用RLock。线程安全不要共享可变对象而不加锁使用Queue或threading 同步原语。GIL 的影响对于 CPU 密集型任务多线程可能比单线程还慢可考虑multiprocessing模块。三socket 和 threading 结合使用socket 和 threading 常结合使用例如在多线程服务器中每个客户端连接分配一个线程处理。典型模式import socket import threading def handle_client(conn, addr): with conn: print(fThread {threading.current_thread().name} handling {addr}) while True: data conn.recv(1024) if not data: break conn.sendall(data) server socket.socket() server.bind((0.0.0.0, 8888)) server.listen(5) while True: conn, addr server.accept() t threading.Thread(targethandle_client, args(conn, addr)) t.start()这样每个连接独立处理主线程继续等待新连接。