Python多TCP套接字实现报错:'int'对象无'recv'属性排查
排查多TCP套接字服务端代码的运行错误
直接触发报错的原因
你遇到的AttributeError: 'int' object has no attribute 'recv'完全是因为线程传参错误:
在启动客户端处理线程时,你错误地把整数1传给了clientthread函数的conn参数:
threading.Thread(target=clientthread,args=(1,)).start()
而clientthread需要的是accept()返回的socket连接对象conn,传int类型进去调用recv()必然报错。正确写法是:
threading.Thread(target=clientthread,args=(conn,)).start()
其他潜在问题(修复后仍需处理)
就算解决了上面的问题,你的代码还有几个会导致运行异常的坑:
- 监听端口的accept逻辑阻塞:当前
while True嵌套for循环遍历监听socket,accept()是阻塞调用,程序会卡在第一个监听socket的accept()上,直到有连接进来,无法同时监听多个端口的连接。要同时处理多个监听端口,应该为每个监听socket单独启动线程,或者用select/poll/epoll做多路复用。 - bytes与字符串拼接错误:
clientthread里buffer是字符串类型,conn.recv()返回的是bytes类型,直接拼接会抛出TypeError。需要先把bytes解码为字符串,还要处理客户端断开的情况(recv()返回空bytes):def clientthread(conn): buffer="" while True: data = conn.recv(8192) if not data: # 客户端断开连接时recv返回空 break buffer += data.decode('utf-8') # 指定编码解码为字符串 print(buffer) print("data recieved") conn.close() - socket资源未完全释放:最后
s.close()只关闭了最后一个创建的监听socket,其余监听socket没有被关闭,应该遍历list_sock逐个关闭。 - 重复导入threading模块:代码同时用了
import threading和from threading import *,属于冗余导入,保留其中一个即可,推荐用import threading避免命名冲突。
修复后的示例代码片段
#!usr/bin/python import threading import socket import sys def clientthread(conn): buffer="" while True: data = conn.recv(8192) if not data: break buffer += data.decode('utf-8') print(buffer) print("data recieved") conn.close() def listen_socket(sock): """为单个监听socket启动线程处理连接""" while True: conn, addr = sock.accept() print('[*] Connected with ' + addr[0] + ':' + str(addr[1])) threading.Thread(target=clientthread, args=(conn,)).start() print(threading.active_count()) def main(): try: host = '10.102.3.16' port = 1000 tot_socket = 6 list_sock = [] for i in range(tot_socket): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) current_port = port * (i+1) s.bind((host, current_port)) s.listen(10) list_sock.append(s) print("[*] Server listening on %s %d" %(host, current_port)) # 为每个监听socket启动独立线程 threading.Thread(target=listen_socket, args=(s,), daemon=True).start() # 主线程保持运行,等待中断信号 while True: pass except KeyboardInterrupt: # 关闭所有监听socket for sock in list_sock: sock.close() sys.exit(0) if __name__ == "__main__": main()
内容的提问来源于stack exchange,提问作者gari
相关产品推荐
相关产品推荐

