Python Socket调用SHUT_RD未中断读取,join阻塞问题求助
问题原因及解决方案
核心原因
你遇到的阻塞问题,根源在于socket的shutdown操作和makefile创建的文件对象缓冲区之间的不兼容:
- 文件对象的缓冲机制:
socket.makefile()会创建带缓冲的文件对象(你指定了rbufsize)。调用shutdown(SHUT_RD)只是关闭了socket的读通道,但文件对象内部的缓冲区可能还有未处理数据,或者readline()会一直等待换行符,直到缓冲区触发EOF条件——单纯的shutdown不会直接让文件对象感知到EOF。 - shutdown的作用范围:
SHUT_RD仅关闭本地读操作,若服务器未主动关闭连接,socket连接本身仍存在。此时socket的recv()可能返回0(表示EOF),但带缓冲的文件对象会继续等待缓冲区填满或换行符,不会立刻返回空。
解决方案
方案1:直接关闭读文件对象
在stop()方法中关闭_rfile,让readline()立刻返回空或抛出异常,终止循环:
def stop(self): if self._rfile and not self._rfile.closed: self._rfile.close()
方案2:shutdown结合文件对象关闭
如果必须保留shutdown操作,需同时关闭文件对象确保缓冲区被处理:
def stop(self): self._socket.shutdown(socket.SHUT_RD) if self._rfile and not self._rfile.closed: self._rfile.close()
方案3:给socket设置超时
通过设置socket超时,避免readline()无限阻塞,同时在stop()中正常退出循环:
def run(self): self._socket.connect(("127.0.0.1", 1777)) # 设置1秒超时,超时后readline会抛出异常 self._socket.settimeout(1) self._rfile = self._socket.makefile('rb', self.rbufsize, encoding=self.encoding, newline=self.new_line) while True: try: data = self._rfile.readline() except socket.timeout: # 超时后检查是否需要停止,或继续循环 continue if not data: break self._handle_data(data) self._cleanup()
额外注意事项
_cleanup()中不要重复调用shutdown(SHUT_RDWR),若stop()中已执行过shutdown,会触发报错,可先检查socket状态。- 用
makefile()创建的读写文件对象共享同一个socket句柄,关闭其中一个会直接影响整个socket。
内容的提问来源于stack exchange,提问作者Forenceur
相关产品推荐
相关产品推荐

