2025-07-01 14:01:38 +08:00
|
|
|
|
import socket
|
|
|
|
|
import json
|
|
|
|
|
import time
|
2025-07-01 14:06:42 +08:00
|
|
|
|
import sys
|
2025-07-01 14:01:38 +08:00
|
|
|
|
from datetime import datetime
|
|
|
|
|
|
2025-07-01 14:06:42 +08:00
|
|
|
|
# 设置标准输出编码为 UTF-8(解决 Windows 控制台编码问题)
|
|
|
|
|
if sys.platform.startswith('win'):
|
|
|
|
|
import codecs
|
|
|
|
|
sys.stdout = codecs.getwriter('utf-8')(sys.stdout.detach())
|
|
|
|
|
sys.stderr = codecs.getwriter('utf-8')(sys.stderr.detach())
|
|
|
|
|
# 设置标准输入编码
|
|
|
|
|
sys.stdin = codecs.getreader('utf-8')(sys.stdin.detach())
|
|
|
|
|
|
2025-07-01 14:01:38 +08:00
|
|
|
|
class JSONSocketClient:
|
|
|
|
|
def __init__(self, host='localhost', port=8888):
|
|
|
|
|
self.host = host
|
|
|
|
|
self.port = port
|
|
|
|
|
self.socket = None
|
|
|
|
|
self.connected = False
|
|
|
|
|
|
|
|
|
|
def connect(self):
|
|
|
|
|
"""连接到服务器"""
|
|
|
|
|
try:
|
|
|
|
|
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
|
|
|
self.socket.connect((self.host, self.port))
|
|
|
|
|
self.connected = True
|
|
|
|
|
print(f"✅ 已连接到服务器 {self.host}:{self.port}")
|
|
|
|
|
return True
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"❌ 连接失败: {e}")
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
def disconnect(self):
|
|
|
|
|
"""断开连接"""
|
|
|
|
|
if self.socket:
|
|
|
|
|
self.socket.close()
|
|
|
|
|
self.connected = False
|
|
|
|
|
print("🔌 已断开连接")
|
|
|
|
|
|
|
|
|
|
def send_request(self, request):
|
|
|
|
|
"""发送请求并接收响应"""
|
|
|
|
|
if not self.connected:
|
|
|
|
|
print("❌ 未连接到服务器")
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# 发送请求
|
|
|
|
|
request_json = json.dumps(request, ensure_ascii=False)
|
|
|
|
|
self.socket.send(request_json.encode('utf-8'))
|
|
|
|
|
print(f"📤 发送请求: {request_json}")
|
|
|
|
|
|
|
|
|
|
# 接收响应
|
|
|
|
|
response_data = self.socket.recv(4096).decode('utf-8')
|
|
|
|
|
response = json.loads(response_data)
|
|
|
|
|
print(f"📥 收到响应: {json.dumps(response, ensure_ascii=False, indent=2)}")
|
|
|
|
|
|
|
|
|
|
return response
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"❌ 请求失败: {e}")
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
def send_message(self, message):
|
|
|
|
|
"""发送普通消息(非 JSON 格式)"""
|
|
|
|
|
if not self.connected:
|
|
|
|
|
print("❌ 未连接到服务器")
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
self.socket.send(message.encode('utf-8'))
|
|
|
|
|
print(f"📤 发送消息: {message}")
|
|
|
|
|
|
|
|
|
|
response_data = self.socket.recv(4096).decode('utf-8')
|
|
|
|
|
response = json.loads(response_data)
|
|
|
|
|
print(f"📥 收到响应: {json.dumps(response, ensure_ascii=False, indent=2)}")
|
|
|
|
|
|
|
|
|
|
return response
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"❌ 发送消息失败: {e}")
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
def get_file(self, filename='test_data.json'):
|
|
|
|
|
"""从服务器获取文件"""
|
|
|
|
|
request = {
|
|
|
|
|
"command": "get_file",
|
|
|
|
|
"filename": filename,
|
|
|
|
|
"timestamp": datetime.now().isoformat()
|
|
|
|
|
}
|
|
|
|
|
return self.send_request(request)
|
|
|
|
|
|
|
|
|
|
def save_file(self, filename, content):
|
|
|
|
|
"""保存文件到服务器"""
|
|
|
|
|
request = {
|
|
|
|
|
"command": "save_file",
|
|
|
|
|
"filename": filename,
|
|
|
|
|
"content": content,
|
|
|
|
|
"timestamp": datetime.now().isoformat()
|
|
|
|
|
}
|
|
|
|
|
return self.send_request(request)
|
|
|
|
|
|
|
|
|
|
def list_files(self):
|
|
|
|
|
"""列出服务器上的 JSON 文件"""
|
|
|
|
|
request = {
|
|
|
|
|
"command": "list_files",
|
|
|
|
|
"timestamp": datetime.now().isoformat()
|
|
|
|
|
}
|
|
|
|
|
return self.send_request(request)
|
|
|
|
|
|
|
|
|
|
def ping(self):
|
|
|
|
|
"""测试服务器连接"""
|
|
|
|
|
request = {
|
|
|
|
|
"command": "ping",
|
|
|
|
|
"timestamp": datetime.now().isoformat()
|
|
|
|
|
}
|
|
|
|
|
return self.send_request(request)
|
|
|
|
|
|
|
|
|
|
def interactive_mode(self):
|
|
|
|
|
"""交互模式"""
|
|
|
|
|
print("\n🎮 进入交互模式")
|
|
|
|
|
print("可用命令:")
|
|
|
|
|
print(" 1. get <filename> - 获取文件")
|
|
|
|
|
print(" 2. save <filename> - 保存文件(会提示输入内容)")
|
|
|
|
|
print(" 3. list - 列出文件")
|
|
|
|
|
print(" 4. ping - 测试连接")
|
|
|
|
|
print(" 5. msg <message> - 发送普通消息")
|
|
|
|
|
print(" 6. quit - 退出")
|
|
|
|
|
print()
|
|
|
|
|
|
|
|
|
|
while self.connected:
|
|
|
|
|
try:
|
|
|
|
|
command = input("👉 请输入命令: ").strip()
|
|
|
|
|
|
|
|
|
|
if not command:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
parts = command.split(' ', 1)
|
|
|
|
|
cmd = parts[0].lower()
|
|
|
|
|
|
|
|
|
|
if cmd == 'quit':
|
|
|
|
|
break
|
|
|
|
|
elif cmd == 'get':
|
|
|
|
|
filename = parts[1] if len(parts) > 1 else 'test_data.json'
|
|
|
|
|
self.get_file(filename)
|
|
|
|
|
elif cmd == 'save':
|
|
|
|
|
filename = parts[1] if len(parts) > 1 else 'new_data.json'
|
|
|
|
|
print("请输入要保存的 JSON 内容(输入空行结束):")
|
|
|
|
|
lines = []
|
|
|
|
|
while True:
|
|
|
|
|
line = input()
|
|
|
|
|
if not line:
|
|
|
|
|
break
|
|
|
|
|
lines.append(line)
|
|
|
|
|
|
|
|
|
|
if lines:
|
|
|
|
|
try:
|
|
|
|
|
content = json.loads('\n'.join(lines))
|
|
|
|
|
self.save_file(filename, content)
|
|
|
|
|
except json.JSONDecodeError as e:
|
|
|
|
|
print(f"❌ JSON 格式错误: {e}")
|
|
|
|
|
elif cmd == 'list':
|
|
|
|
|
self.list_files()
|
|
|
|
|
elif cmd == 'ping':
|
|
|
|
|
self.ping()
|
|
|
|
|
elif cmd == 'msg':
|
|
|
|
|
message = parts[1] if len(parts) > 1 else "Hello Server!"
|
|
|
|
|
self.send_message(message)
|
|
|
|
|
else:
|
|
|
|
|
print(f"❌ 未知命令: {cmd}")
|
|
|
|
|
|
|
|
|
|
print() # 空行分隔
|
|
|
|
|
|
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
|
break
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"❌ 命令执行错误: {e}")
|
|
|
|
|
|
|
|
|
|
print("👋 退出交互模式")
|
|
|
|
|
|
|
|
|
|
def test_client():
|
|
|
|
|
"""测试客户端功能"""
|
|
|
|
|
client = JSONSocketClient()
|
|
|
|
|
|
|
|
|
|
print("🧪 开始测试客户端...")
|
|
|
|
|
|
|
|
|
|
# 连接服务器
|
|
|
|
|
if not client.connect():
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# 测试 1: Ping
|
|
|
|
|
print("\n--- 测试 1: Ping ---")
|
|
|
|
|
client.ping()
|
|
|
|
|
|
|
|
|
|
# 测试 2: 列出文件
|
|
|
|
|
print("\n--- 测试 2: 列出文件 ---")
|
|
|
|
|
client.list_files()
|
|
|
|
|
|
|
|
|
|
# 测试 3: 获取文件
|
|
|
|
|
print("\n--- 测试 3: 获取文件 ---")
|
|
|
|
|
client.get_file('test_data.json')
|
|
|
|
|
|
|
|
|
|
# 测试 4: 保存文件
|
|
|
|
|
print("\n--- 测试 4: 保存文件 ---")
|
|
|
|
|
test_content = {
|
|
|
|
|
"message": "这是客户端测试数据",
|
|
|
|
|
"timestamp": datetime.now().isoformat(),
|
|
|
|
|
"data": {
|
|
|
|
|
"name": "测试用户",
|
|
|
|
|
"age": 25,
|
|
|
|
|
"hobbies": ["编程", "音乐", "阅读"]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
client.save_file('client_test.json', test_content)
|
|
|
|
|
|
|
|
|
|
# 测试 5: 发送普通消息
|
|
|
|
|
print("\n--- 测试 5: 发送普通消息 ---")
|
|
|
|
|
client.send_message("Hello Server! This is a test message.")
|
|
|
|
|
|
|
|
|
|
print("\n✅ 所有测试完成!")
|
|
|
|
|
|
|
|
|
|
finally:
|
|
|
|
|
client.disconnect()
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
import sys
|
|
|
|
|
|
|
|
|
|
if len(sys.argv) > 1 and sys.argv[1] == 'test':
|
|
|
|
|
# 运行测试
|
|
|
|
|
test_client()
|
|
|
|
|
else:
|
|
|
|
|
# 交互模式
|
|
|
|
|
client = JSONSocketClient()
|
|
|
|
|
if client.connect():
|
|
|
|
|
try:
|
|
|
|
|
client.interactive_mode()
|
|
|
|
|
finally:
|
|
|
|
|
client.disconnect()
|