同一个Socket实例第二次无法接收服务端数据!! (暂时占用一下首页,请多包涵,该问题困扰我两天了)...

探讨了服务端通过两个线程处理客户端请求的方法,其中一个线程负责接收连接并将其添加到队列,另一个线程从队列中取出连接进行异步收发操作。客户端通过连接池管理多个服务端连接,但在重复使用连接时遇到数据接收失败的问题。
服务端:创建了两个线程来处理客户端请求,一个线程用于接收连接进来的Socket,并将Socket添加到一个队列Queue对象中;另外一个线程用于将Queue中的Socket提出来进行接收、发送操作,接收、发送操作采用异步方式。

客户端:用连接到服务端的Socket创建一个NetworkStream的实例(NetworkStream stream = new NetworkStream(socket, true);),并将该NetworkStream的实例,包装到一个System.IO.BufferedStream的实例中(/*用于接收*/Stream inStream = new BufferedStream(stream); /*用于发送*/Stream outStream = new BufferedStream(stream);)进行与服务端的数据收发。

然后我创建了一个连接池,初始化创建了10个服务端的连接,然后写了一个单线程的测试程序,从连接池中将这10个连接依次取出来发送、接收数据,一切OK(将连接都还回了连接池),但当我再次从连接池取出一个连接(已用完10个创建的连接,这次是第二次取出的连接,在前面是已经使用过的)进行发送、接收数据时,测试程序无法接收到服务端的返回的数据。(不管在客户端还是服务端,在发送/接收完数据后,我都没有关闭连接

从服务端的日志看,服务端是接收到了客户端发来的数据的,并且服务端也成功将数据发送出去了,只是客户端没有接收到。

此问题困扰在下两天了,望达人指教~

转载于:https://www.cnblogs.com/uimeet/archive/2008/12/24/1361183.html

<think> 根据用户需求,需要编写一个可长期运行、能接收个客户端数据的Python TCP Socket服务端代码。要求使用socket模块,支持客户端连接,并且服务端能持续运行。 关键点: 1. 使用`socket`模块创建TCP Socket。 2. 绑定地址和端口,并设置监听。 3. 使用循环持续接受客户端连接。 4. 每个客户端连接都需要在一个单独的线程中处理,以避免阻塞其他连接。 5. 服务端需要能够同时处理个客户端,因此需要线程或异步处理。 6. 服务端应长期运行,直到手动终止。 设计方案: - 主线程负责接受客户端连接,每当有一个新的客户端连接,就创建一个新线程来处理该客户端的通信。 - 处理客户端通信的线程需要负责接收和发送数据,并在客户端断开后关闭连接。 参考引用中的代码片段,特别是引用[3]提供了客户端连接的处理,但它是单线程顺序处理,无法同时处理个客户端。因此需要改进为线程。 编写代码: ```python import socket import threading def handle_client(client_socket, client_address): """ 处理客户端连接 :param client_socket: 客户端socket对象 :param client_address: 客户端地址和端口 """ print(f"新客户端连接: {client_address}") try: while True: # 接收数据,缓冲区大小为1024 data = client_socket.recv(1024) if not data: break # 客户端断开连接 # 将接收到的数据解码(假设是UTF-8编码) data_str = data.decode('utf-8') print(f"收到来自 {client_address} 的消息: {data_str}") # 回复消息 response = f"服务端已收到消息: {data_str}" client_socket.sendall(response.encode('utf-8')) except Exception as e: print(f"与客户端 {client_address} 通信时发生错误: {e}") finally: # 关闭客户端连接 client_socket.close() print(f"客户端 {client_address} 连接已关闭") def start_server(host='0.0.0.0', port=12345): """ 启动TCP服务端 :param host: 监听的主机地址,默认为所有可用地址 :param port: 监听的端口 """ # 创建TCP socket server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 设置地址重用,避免端口占用问题 server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 绑定地址和端口 server_socket.bind((host, port)) # 开始监听,设置最大连接数 server_socket.listen(5) print(f"服务端启动,监听 {host}:{port} ...") try: while True: # 接受客户端连接 client_socket, client_address = server_socket.accept() # 创建线程处理客户端 client_thread = threading.Thread(target=handle_client, args=(client_socket, client_address)) client_thread.daemon = True # 设置为守护线程,主线程退出时自动结束 client_thread.start() print(f"活跃线程数: {threading.active_count() - 1}") # 减去主线程 except KeyboardInterrupt: print("服务端被用户中断.") except Exception as e: print(f"服务端发生错误: {e}") finally: server_socket.close() print("服务端已关闭.") if __name__ == "__main__": start_server() ``` 代码说明: 1. `handle_client`函数:每个客户端连接都会在一个独立的线程中运行此函数,负责与客户端通信。循环接收客户端数据,并回复确认消息,直到客户端断开连接。 2. `start_server`函数:创建服务端socket,绑定地址和端口,并开始监听。主循环中接受客户端连接,并为每个连接启动一个新线程。 3. 设置`client_thread.daemon = True`使得这些线程成为守护线程,这样当主线程退出时,所有客户端线程也会自动退出。 4. 使用`try-except`捕获中断信号(如Ctrl+C),以便优雅关闭服务端。 注意事项: - 此代码使用线程处理客户端,适用于并发连接数不是特别高的情况(例如几百个)。如果连接数非常高,可能需要考虑使用异步IO(如asyncio)或线程池。 - 服务端默认监听所有可用网络接口(`0.0.0.0`)的12345端口,可以根据需要修改。 - 每个客户端连接都会打印日志,包括收到的消息和连接状态。 用户可以直接运行此代码启动服务端服务端会一直运行,直到用户按下Ctrl+C中断。 相关问题: 1. 如何处理大量客户端连接时的性能问题? 2. 如何保证TCP Socket通信的可靠性? 3. Python中除了线程,还有哪些方式可以实现客户端连接? </think> ### Python TCP Socket 服务端代码(客户端支持) 以下是可长期运行、能接收个客户端数据的Python TCP Socket服务端代码,使用线程技术实现并发处理: ```python import socket import threading import time def client_handler(client_socket, client_address): """ 处理单个客户端连接 :param client_socket: 客户端socket对象 :param client_address: 客户端地址(IP, 端口) """ print(f"[+] 客户端 {client_address} 已连接") try: while True: # 接收客户端数据(最大1024字节) data = client_socket.recv(1024) if not data: break # 客户端断开连接 # 处理接收到的数据 message = data.decode('utf-8') print(f"收到来自 {client_address} 的消息: {message}") # 发送响应(可自定义业务逻辑) timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) response = f"服务端已收到消息 [{timestamp}]: {message}" client_socket.send(response.encode('utf-8')) except ConnectionResetError: print(f"[-] 客户端 {client_address} 异常断开") finally: client_socket.close() print(f"[-] 客户端 {client_address} 连接已关闭") def start_server(host='0.0.0.0', port=9999): """ 启动TCP服务端 :param host: 监听的主机地址(默认所有接口) :param port: 监听端口 """ # 创建TCP socket server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 设置地址重用选项 server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 绑定地址和端口 server_socket.bind((host, port)) # 开始监听,设置最大等待连接数 server_socket.listen(5) print(f"[*] 服务端启动,监听 {host}:{port} ...") try: while True: # 接受客户端连接 client_sock, addr = server_socket.accept() # 创建新线程处理客户端 client_thread = threading.Thread( target=client_handler, args=(client_sock, addr) ) client_thread.daemon = True # 设置为守护线程 client_thread.start() print(f"[*] 活跃客户端线程数: {threading.active_count() - 1}") except KeyboardInterrupt: print("\n[*] 服务端关闭中...") finally: server_socket.close() print("[*] 服务端已关闭") if __name__ == "__main__": start_server() # 默认监听所有接口的9999端口 ``` ### 代码说明 1. **线程架构** - 主线程负责接收新连接 - 每个客户端连接创建独立线程处理 - 使用`daemon=True`确保主程序退出时自动关闭所有线程 2. **核心功能** - 持续监听客户端连接(`server_socket.accept()`) - 接收客户端消息(`recv(1024)`) - 发送响应消息(`send()`) - 自动处理客户端断开连接 3. **长期运行特性** - 使用无限循环维持服务 - 异常捕获确保资源释放 - 支持`KeyboardInterrupt`(Ctrl+C)优雅退出 4. **地址重用选项** - `setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)` 避免端口占用问题 ### 使用方法 1. 保存为`server.py` 2. 运行服务端: ```bash python server.py ``` 3. 使用客户端连接: - 可使用`telnet 127.0.0.1 9999`测试 - 或创建Python客户端(参考下方客户端代码) ### 客户端测试代码 ```python # client.py import socket def start_client(host='127.0.0.1', port=9999): client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect((host, port)) try: while True: msg = input("发送消息(输入exit退出): ") if msg.lower() == 'exit': break client.send(msg.encode('utf-8')) response = client.recv(1024).decode('utf-8') print(f"服务端回复: {response}") finally: client.close() if __name__ == "__main__": start_client() ``` ### 注意事项 1. **端口选择**:确保防火墙允许所选端口(如9999)的通信 2. **编码处理**:使用UTF-8编码处理文本数据 3. **资源管理**:大量连接时考虑使用线程池(`ThreadPoolExecutor`) 4. **错误处理**:实际生产环境需要更完善的异常处理机制 此服务端代码满足长期运行需求,可同时处理个客户端连接,每个连接独立线程处理,避免阻塞主线程[^1][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值