python网络编程核心是socket模块,通过它可直接操作tcp/udp协议实现服务器与客户端通信。1. tcp服务器端流程:创建socket对象→绑定ip和端口→监听连接→接受客户端连接→接收/发送数据→关闭连接。2. tcp客户端流程:创建socket对象→连接服务器→发送/接收数据→关闭连接。3. 数据传输需注意:sendall()确保完整发送;recv()需处理粘包问题,应用层可通过“长度+数据”协议解决。4. 编码解码需统一使用encode()/decode()。5. 并发处理可通过多线程、多进程或i/o多路复用(如selectors模块)实现。6. 常见问题及解决:地址被占用可设置so_reuseaddr;连接被拒绝需检查服务状态和防火墙;数据接收不完整需设计协议;broken pipe需检测连接状态;阻塞问题可设超时或使用非阻塞+i/o复用。

Python的网络编程,说到底,核心就是
socket

要用Python进行网络编程,特别是基于TCP的Socket通信,基本流程其实挺清晰的,虽然初次接触可能会觉得有点绕。简单来说,就是服务器端和客户端各司其职。
TCP服务器端:
立即学习“Python免费学习笔记(深入)”;

socket.socket(socket.AF_INET, socket.SOCK_STREAM)
AF_INET
SOCK_STREAM
s.bind(('127.0.0.1', 8888))127.0.0.1
8888
s.listen(5)
conn, addr = s.accept()
conn
addr
conn.recv(1024)
conn.sendall(data)
encode()
decode()
conn.close()
s.close()
TCP客户端:
socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 8888))s.sendall(data)
s.recv(1024)
s.close()
这是一个简单的Echo服务器和客户端的例子,你可以感受一下:

服务器端 (server.py):
import socket
HOST = '127.0.0.1' # 标准回环接口地址
PORT = 65432 # 非特权端口 > 1023
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
print(f"服务器正在监听 {HOST}:{PORT}...")
conn, addr = s.accept() # 阻塞,直到有客户端连接
with conn:
print(f"连接自: {addr}")
while True:
data = conn.recv(1024) # 接收数据,缓冲区大小1024字节
if not data: # 如果没有数据,说明客户端断开连接
print(f"客户端 {addr} 已断开。")
break
print(f"收到来自 {addr} 的消息: {data.decode()}")
conn.sendall(data) # 把收到的数据原样发回去
print(f"已回发给 {addr}")客户端 (client.py):
import socket
HOST = '127.0.0.1' # 服务器的IP地址
PORT = 65432 # 服务器的端口
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT)) # 连接服务器
message = "Hello, server! This is client."
s.sendall(message.encode()) # 发送编码后的数据
print(f"已发送: '{message}'")
data = s.recv(1024) # 接收服务器回传的数据
print(f"收到回显: {data.decode()}")运行的时候,先启动
server.py
client.py
在Socket通信中,数据流动远不止
send
recv
首先,
send()
sendall()
send()
send()
sendall()
sendall()
再来说说接收数据,也就是
recv(bufsize)
bufsize
recv
举个例子,客户端连续发送两条消息“Hello”和“World”,服务器端一次
recv
数据的编码和解码也是个常被忽略但又很重要的点。Python 3里字符串是Unicode,但网络传输的是字节流。所以,发送前必须调用
.encode('utf-8').decode('utf-8')上面那个简单的Echo服务器,它一次只能处理一个客户端连接。当一个客户端连接上来后,服务器就会被“卡住”,直到这个客户端断开,才能接受下一个连接。这显然无法满足现代网络应用的需求,想想微信、淘宝,那得同时处理多少用户啊!
要让服务器能同时服务多个客户端,我们通常会考虑几种并发策略。
一种比较直观的方式是多线程(threading)或多进程(multiprocessing)。当服务器接受到一个新的客户端连接时,它可以创建一个新的线程或进程来专门处理这个客户端的通信。这样,主线程(或主进程)就可以继续监听新的连接请求了。
这两种方式,代码实现起来都相对直接,你只需要在
s.accept()
conn
addr
# 多线程服务器伪代码
import socket
import threading
def handle_client(conn, addr):
print(f"新线程处理连接自: {addr}")
with conn:
while True:
data = conn.recv(1024)
if not data:
break
print(f"收到来自 {addr} 的消息: {data.decode()}")
conn.sendall(data)
print(f"线程 {addr} 已结束。")
# ... (服务器初始化代码) ...
# s.listen()
while True:
conn, addr = s.accept()
client_thread = threading.Thread(target=handle_client, args=(conn, addr))
client_thread.start()另一种更高级、更高效的方式是I/O多路复用(I/O Multiplexing)。这不是为每个连接创建一个线程或进程,而是用一个(或少数几个)线程来同时监控多个Socket连接的状态。当某个Socket准备好读写时,操作系统会通知你。Python的
select
selectors
asyncio
I/O多路复用避免了创建大量线程/进程的开销,尤其适用于连接数非常多但每个连接的I/O操作并不频繁的场景(比如聊天服务器)。它让单个线程能够“同时”管理成千上万个连接,效率非常高。理解
select
epoll
网络编程这东西,说不准什么时候就给你来个“惊喜”。我自己在写Socket应用的时候,也遇到过不少让人头疼的问题。提前知道这些坑,至少能让你在遇到的时候不那么慌乱。
Address already in use
s.bind()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
Connection refused
数据接收不完整或粘包:前面提过,
recv()
Broken pipe
Connection reset by peer
recv()
阻塞I/O导致程序卡死:默认情况下,
socket.accept()
socket.recv()
s.settimeout(timeout_seconds)
socket.timeout
s.setblocking(False)
accept()
recv()
BlockingIOError
WouldBlockError
select
selectors
调试Socket程序时,除了常规的打印日志和断点调试,我发现网络抓包工具(比如Wireshark)简直是神器。它能让你看到网络上实际传输的每一个数据包,包括TCP握手、数据内容、各种标志位,这对于理解网络行为和定位问题非常有帮助。很多时候,代码看起来没问题,但网络层面的一个小细节就可能导致意想不到的行为。
以上就是Python如何做网络编程?Socket通信教程的详细内容,更多请关注php中文网其它相关文章!
编程怎么学习?编程怎么入门?编程在哪学?编程怎么学才快?不用担心,这里为大家提供了编程速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号