Python Socket实现服务端向客户端返回ping结果的问题咨询
现有代码问题排查
- 服务端返回逻辑位置错误:
conn.sendall(dataFromClient)放在了客户端断开连接的break之后,只有客户端下线才会执行,且此时dataFromClient为空,无法正常返回数据 - 业务逻辑颠倒:ping操作的执行逻辑写在了客户端,不符合「服务端发起ping」的需求
- 客户端收包逻辑被注释,无法接收服务端的任何返回内容
- 无统一的指令/返回协议,两端无法识别对方发送的内容含义
- 未处理TCP粘包问题,长输出内容会出现乱码、拼接错误
实现方案
我们先约定统一的交互协议:
- 连接建立后,客户端发送
check指令,服务端返回online即代表服务端在线 - 客户端发送ping指令格式为
ping|目标IP| ping次数,例如ping|223.5.5.5|4 - 服务端返回内容末尾统一加
[EOF]作为结束标记,解决TCP粘包问题
修正后服务端代码
#!/usr/bin/python3 import socket import sys import subprocess import platform HOST = '0.0.0.0' # 本地测试可保留127.0.0.1,改0.0.0.0允许外网客户端连接 PORT = 8085 # 跨平台ping命令参数适配 ping_param = '-n' if platform.system().lower() == 'windows' else '-c' s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print('Socket created') # 绑定端口 try: s.bind((HOST, PORT)) except socket.error as msg: print(f'Bind failed. Error Code : {msg[0]} Message {msg[1]}') sys.exit() print('Socket bind complete') # 启动端口监听 s.listen(10) print('Socket now listening') while 1: conn, addr = s.accept() print(f'Connected from {addr}') while True: dataFromClient = conn.recv(1024).decode('utf-8').strip() if not dataFromClient: print("[Client] Disconnected") break print(f"Received command: {dataFromClient}") # 处理在线检测指令 if dataFromClient == 'check': conn.sendall(b'online[EOF]') # 处理ping指令 elif dataFromClient.startswith('ping|'): _, target, count = dataFromClient.split('|') cmd = ['ping', ping_param, count, target] try: result = subprocess.run(cmd, capture_output=True, text=True, timeout=10) output = result.stdout + result.stderr except Exception as e: output = f"Ping execution error: {str(e)}" conn.sendall(f"{output}[EOF]".encode('utf-8')) # 未知指令处理 else: conn.sendall(b'Unknown command[EOF]') conn.close() s.close()
修正后客户端代码
#!/usr/bin/python3 import socket import os SERVER = "127.0.0.1" PORT = 8085 def recv_full_data(sock): """接收完整数据直到遇到结束标记[EOF],解决TCP粘包问题""" data = b'' while True: part = sock.recv(1024) if not part: break data += part if b'[EOF]' in data: break return data.replace(b'[EOF]', b'').decode('utf-8') clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: clientSocket.connect((SERVER, PORT)) except Exception as e: print(f"Connect to server failed: {str(e)}") exit() os.system("clear||cls") while True: data = input("Input: ").strip() if not data: continue # 退出指令 if data == 'exit': break # 发送指令给服务端 clientSocket.send(data.encode('utf-8')) # 接收服务端返回 resp = recv_full_data(clientSocket) if data == "check": print(f"Server status: {resp}") elif data == "ping": target = input("Enter ping target IP: ").strip() count = input("Enter ping times: ").strip() # 拼装ping指令发送 clientSocket.send(f"ping|{target}|{count}".encode('utf-8')) ping_result = recv_full_data(clientSocket) print("Ping result from server:") print(ping_result) elif data == "help": print("Supported commands:") print("- check: Check if server is online") print("- ping: Execute ping on server and get result") print("- help: Show help info") print("- exit: Exit client") else: print(f"Server response: {resp}") clientSocket.close()
使用说明
- 先启动服务端脚本,再启动客户端脚本
- 客户端输入
check即可检测服务端是否在线 - 客户端输入
ping按照提示输入目标IP和ping次数,即可获取服务端执行的ping原始输出 - 客户端输入
help可查看所有支持的指令 - 客户端输入
exit即可退出
内容的提问来源于stack exchange,提问作者whipflashx
相关产品推荐
相关产品推荐

