Python 2简易Socket服务器:recv返回0及errno10035问题排查
解决非阻塞Socket的errno 10035错误 & 理解recv返回0的场景
嘿,我来帮你理清楚这个问题!咱们一步步拆解:
首先,errno 10035对应Windows下的WSAEWOULDBLOCK错误——当你把套接字设为非阻塞模式后,调用recv()时如果当前没有可读取的数据,它不会像阻塞模式那样一直等待,而是直接抛出这个异常,告诉你「现在没数据,稍后再试」。你的代码里没处理这个异常,所以才会触发报错。
修复错误的代码示例
我把你的代码补全并修改了异常处理逻辑,同时修正了原代码里的小问题(比如print语法、未完成的字符串占位):
import socket import time def Main(): host = "" port = 80 indic = 1 data = "" s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((host, port)) s.listen(1) c, addr = s.accept() c.setblocking(0) print "Connection from: " + str(addr) while indic: try: data = c.recv(4096) if not data: # 这里就是recv返回空串(等效于返回0的逻辑)的场景 print "Client has closed the connection" indic = 0 else: print "From connected user: " + data.strip() except socket.error as e: # 捕获WSAEWOULDBLOCK错误 if e.errno == 10035: # 暂时没数据,稍作等待后重试 time.sleep(0.1) continue else: # 处理其他异常,比如连接意外中断 print "Socket error occurred: ", e indic = 0 c.close() s.close() if __name__ == "__main__": Main()
关于recv返回0的场景
recv()返回空字节串(Python 2里是'',Python 3里是b''),只有当客户端主动关闭连接,并且服务器已经接收完该连接上的所有残留数据时才会发生。
举个实际场景:客户端调用socket.close()主动断开套接字,服务器这边的recv()在读完所有剩余数据后,下一次调用就会返回空串——这就是你要的「recv返回0」的判定条件,此时你可以确定客户端已断开,关闭服务器侧的套接字并退出循环即可。
另外补充一个更优雅的非阻塞处理方案:用select模块监听套接字的可读事件,避免频繁sleep和异常捕获,效率更高:
import socket import select def Main(): host = "" port = 80 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((host, port)) s.listen(1) c, addr = s.accept() c.setblocking(0) print "Connection from: " + str(addr) while True: # 监听可读套接字,超时时间设为1秒 readable, _, _ = select.select([c], [], [], 1) if c in readable: data = c.recv(4096) if not data: print "Client disconnected" break print "From connected user: " + data.strip() c.close() s.close() if __name__ == "__main__": Main()
内容的提问来源于stack exchange,提问作者user378298
相关产品推荐
相关产品推荐

