python socket

cpp 复制代码
import socket
import threading
import sys
import time


class TCPClientTest:
    """TCP客户端 - 适配多客户端服务器,支持发送1/2/3指令并接收响应"""

    def __init__(self, host="127.0.0.1", port=8888):
        self.client_socket = None
        self.host = host
        self.port = port
        self.is_connected = False  # 连接状态标记
        self.recv_thread = None  # 接收响应的线程

    def connect_to_server(self):
        """连接到TCP服务器"""
        try:
            # 创建客户端套接字
            self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            # 设置超时(避免连接卡住)
            self.client_socket.settimeout(10)
            # 连接服务器
            self.client_socket.connect((self.host, self.port))
            self.is_connected = True
            print(f"[客户端] 成功连接到服务器 {self.host}:{self.port}")

            # 启动接收响应的线程(后台持续接收服务器消息)
            self.recv_thread = threading.Thread(target=self.receive_messages, daemon=True)
            self.recv_thread.start()

            return True
        except socket.timeout:
            print(f"[客户端] 连接超时 - 服务器 {self.host}:{self.port} 未响应")
            return False
        except ConnectionRefusedError:
            print(f"[客户端] 连接失败 - 服务器 {self.host}:{self.port} 未启动或拒绝连接")
            return False
        except Exception as e:
            print(f"[客户端] 连接异常: {str(e)}")
            return False

    def receive_messages(self):
        """后台接收服务器响应的线程"""
        print("[接收线程] 已启动,等待服务器消息...")
        while self.is_connected:
            try:
                # 接收服务器数据(缓冲区1024字节)
                recv_data = self.client_socket.recv(1024).decode('utf-8').strip()
                if not recv_data:
                    print("[客户端] 服务器主动断开连接")
                    self.is_connected = False
                    break
                # 打印服务器响应
                print(f"\n[服务器响应] {recv_data}")
                print("根据接收到数据,do something")
                self.recvdata = recv_data
            except socket.timeout:
                continue  # 超时继续等待
            except Exception as e:
                if self.is_connected:
                    print(f"\n[接收异常] {str(e)}")
                break

    def send_command(self, command):
        """发送指令到服务器"""
        if not self.is_connected or self.client_socket is None:
            print("[发送失败] 未连接到服务器")
            return False

        try:
            # 编码并发送指令
            self.client_socket.sendall(command.encode('utf-8'))
            print(f"\n[发送成功] 指令: {command}")
            return True
        except BrokenPipeError:
            print("[发送失败] 连接已断开(Broken Pipe)")
            self.is_connected = False
            return False
        except Exception as e:
            print(f"[发送异常] {str(e)}")
            self.is_connected = False
            return False

    def disconnect(self):
        """断开与服务器的连接"""
        self.is_connected = False
        if self.client_socket:
            try:
                self.client_socket.close()
                print("[客户端] 已断开与服务器的连接")
            except Exception as e:
                print(f"[关闭异常] {str(e)}")


def main():
    # 创建客户端实例(可修改host/port适配你的服务器)
    client = TCPClientTest(host="127.0.0.1", port=8888)

    # 连接服务器
    if not client.connect_to_server():
        sys.exit(1)

    # 交互输入指令
    print("\n=== 客户端操作说明 ===")
    print("输入 1/2/3 发送对应指令到服务器")
    print("输入 quit 退出客户端")
    print("======================\n")

    try:
        while client.is_connected:
            # 手动输入指令
            command = input("请输入指令(1/2/3)或输入quit退出: ").strip()

            # 退出逻辑
            if command.lower() == "quit":
                client.disconnect()
                break

            client.send_command(command)


    except KeyboardInterrupt:
        print("\n\n[用户操作] 检测到Ctrl+C,正在退出...")
        client.disconnect()
    except Exception as e:
        print(f"\n[客户端异常] {str(e)}")
        client.disconnect()


if __name__ == "__main__":
    main()
cpp 复制代码
import socket
import threading
import time
import uuid


class TCPServerTest:
    """TCP服务器测试类 - 支持多客户端并发,接1发送get 1,仅Ctrl+C关闭"""
    def __init__(self):
        self.server_socket = None
        self.is_server_running = False  # 服务器总运行标记
        self.clients = {}  # 客户端连接池: {client_id: (client_socket, address, thread)}
        self.clients_lock = threading.Lock()  # 保护客户端连接池的线程锁
        self.recv_data = {}  # 每个客户端的接收缓冲区: {client_id: data_str}
        self.recv_data_lock = threading.Lock()  # 保护接收缓冲区的锁
        self.HOST = "127.0.0.1"
        self.PORT = 8888
        self.BUFFER_SIZE = 1024

    def is_socket_valid(self, sock):
        """检查套接字有效性"""
        if sock is None:
            return False
        try:
            return sock.fileno() != -1
        except (OSError, AttributeError):
            return False

    def handle_client(self, client_socket, address, client_id):
        """处理单个客户端的通信(独立线程)"""
        print(f"[客户端{client_id}] 已连接 - 地址: {address[0]}:{address[1]}")
        # 连接成功立即返回OK
        self.send_message(client_id, "OK")
        while self.is_server_running:
            try:
                if not self.is_socket_valid(client_socket):
                    break

                # 接收客户端数据
                recv_data = client_socket.recv(self.BUFFER_SIZE).decode('utf-8').strip()
                if not recv_data:  # 客户端主动断开
                    print(f"[客户端{client_id}] 主动断开连接")
                    break

                # 存储接收到的数据到对应客户端的缓冲区
                with self.recv_data_lock:
                    if client_id not in self.recv_data:
                        self.recv_data[client_id] = ""
                    self.recv_data[client_id] += recv_data
                    print(f"[客户端{client_id}] 收到数据: {recv_data} | 累计: {self.recv_data[client_id]}")
            except Exception as e:
                print(f"[客户端{client_id}] 通信异常: {str(e)}")
                break

        # 客户端断开,清理资源
        with self.clients_lock:
            if client_id in self.clients:
                del self.clients[client_id]
        with self.recv_data_lock:
            if client_id in self.recv_data:
                del self.recv_data[client_id]

        client_socket.close()
        print(f"[客户端{client_id}] 连接已清理 | 当前在线客户端数: {len(self.clients)}")

    def send_message(self, client_id, send_data):
        """向指定客户端发送数据"""
        with self.clients_lock:
            if client_id not in self.clients:
                print(f"[发送失败] 客户端{client_id}不存在")
                return -1

            client_socket, _, _ = self.clients[client_id]

        if not self.is_socket_valid(client_socket):
            print(f"[发送失败] 客户端{client_id}套接字无效")
            return -1

        try:
            data_bytes = send_data.encode("utf-8")
            client_socket.sendall(data_bytes)
            print(f"[客户端{client_id}] 发送成功: {send_data}")
            return 1
        except Exception as e:
            print(f"[客户端{client_id}] 发送失败: {str(e)}")
            return -1

    def broadcast_message(self, send_data):
        """广播消息给所有在线客户端"""
        with self.clients_lock:
            online_clients = list(self.clients.keys())

        for client_id in online_clients:
            self.send_message(client_id, send_data)
        print(f"[广播] 已发送: {send_data} | 覆盖客户端数: {len(online_clients)}")

    def start_server(self):
        """启动服务器,持续监听多客户端连接"""
        try:
            # 创建服务器套接字
            self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
            self.server_socket.bind((self.HOST, self.PORT))
            self.server_socket.listen(10)  # 增大监听队列,支持更多并发连接
            self.is_server_running = True

            print(f"[服务器启动成功] 监听 {self.HOST}:{self.PORT}")
            print(f"[核心特性] 多客户端并发 | 接收到1立即发送get 1 | 按 Ctrl+C 关闭服务器\n")

            # 持续接受新客户端连接
            while self.is_server_running:
                try:
                    client_socket, address = self.server_socket.accept()
                    client_id = str(uuid.uuid4())[:8]  # 生成短UUID作为客户端ID

                    # 创建客户端处理线程
                    client_thread = threading.Thread(
                        target=self.handle_client,
                        args=(client_socket, address, client_id),
                        daemon=True
                    )
                    client_thread.start()

                    # 将客户端信息加入连接池
                    with self.clients_lock:
                        self.clients[client_id] = (client_socket, address, client_thread)

                    print(f"[新客户端] ID:{client_id} | 当前在线客户端数: {len(self.clients)}")

                except Exception as e:
                    if self.is_server_running:
                        print(f"[接受连接异常] {str(e)},1秒后重试...")
                        time.sleep(1)

        except Exception as e:
            print(f"[服务器启动失败] {str(e)}")
            self.is_server_running = False
        finally:
            # 关闭服务器时清理所有客户端连接
            self.stop_server()

    def stop_server(self):
        """关闭服务器,清理所有资源"""
        self.is_server_running = False

        # 关闭所有客户端连接
        with self.clients_lock:
            for client_id in list(self.clients.keys()):
                client_socket, _, _ = self.clients[client_id]
                if self.is_socket_valid(client_socket):
                    client_socket.close()
                del self.clients[client_id]

        # 关闭服务器套接字
        if self.is_socket_valid(self.server_socket):
            self.server_socket.close()

        print("[服务器] 已关闭,所有客户端连接已清理")

    def process_client_commands(self):
        """处理客户端指令(核心修改:接1发送get 1),独立线程运行"""
        print("in process_client_commands")

        while self.is_server_running:
            time.sleep(0.1)  # 降低轮询频率,减少资源占用
            with self.recv_data_lock:
                # 遍历所有客户端的接收缓冲区
                for client_id in list(self.recv_data.keys()):
                    data = self.recv_data[client_id]
                    if not data:
                        continue

                    # 核心修改:接收到1,立即发送get 1给对应客户端
                    if "1" == data:
                        print(f"[客户端{client_id}] 检测到指令1,执行响应")
                        self.send_message(client_id, "1 do operator")

                    # 保留2/3指令处理(如需修改可直接改响应内容,格式同上面)
                    if "2" == data:
                        print(f"[客户端{client_id}] 检测到指令2,执行响应")
                        self.send_message(client_id, "2 do operator")

                    if "3" == data:
                        print(f"[客户端{client_id}] 检测到指令3,执行响应")
                        self.send_message(client_id, "3 do operator")

                    self.recv_data[client_id] = ""



if __name__ == "__main__":
    # 实例化服务器
    server = TCPServerTest()

    # 启动服务器主线程(监听客户端连接)
    server_thread = threading.Thread(target=server.start_server, daemon=True)
    server_thread.start()
    time.sleep(2)

    # 测试:启动指令处理线程(核心:接1发get 1)
    # cmd_thread = threading.Thread(target=server.process_client_commands, daemon=True)
    # cmd_thread.start()
    server.process_client_commands()
    # 主线程永久阻塞,仅Ctrl+C退出
    # try:
    #     while True:
    #         time.sleep(1)
    #         # 可选:打印当前在线客户端数(取消注释即可)
    #         # with server.clients_lock:
    #         #     print(f"\r[当前在线] {len(server.clients)} 个客户端", end="")
    # except KeyboardInterrupt:
    #     print("\n\n[用户操作] 检测到Ctrl+C,正在关闭服务器...")
    #     server.stop_server()
    #     time.sleep(1)
    #     print("[服务器] 已完全关闭,程序退出")
相关推荐
玩大数据的龙威2 小时前
农经权二轮延包—一键出承包地块调查表
数据库·python
缺点内向2 小时前
告别“复制粘贴”:用C#和模板高效生成Word文档
开发语言·c#·word
edisao2 小时前
【开源】轻量级 LLM 文本质检工具:精准识别核心概念缺失,支持动态别名 + 反馈闭环
大数据·开发语言·人工智能·经验分享·gpt·架构·开源
爱吃肉的鹏2 小时前
树莓派4B安装pytorch
人工智能·pytorch·python
Leweslyh2 小时前
【实战】如何在家定位国际空间站 (ISS)? —— 坐标转换的魔法 (例题 5.9)
开发语言·javascript·ecmascript
Sheep Shaun2 小时前
深入理解AVL树:从概念到完整C++实现详解
服务器·开发语言·数据结构·c++·后端·算法
_leoatliang2 小时前
基于Python的深度学习以及常用环境测试案例
linux·开发语言·人工智能·python·深度学习·算法·ubuntu
leiming62 小时前
C语言联合体union的用法(非常详细,附带示例)
java·python·算法
少控科技2 小时前
QT新手日记025 - W002程序代码
开发语言·qt