From eb247f29b552882dabef310261d40e113922d27a Mon Sep 17 00:00:00 2001 From: DZY Date: Mon, 2 Jun 2025 14:27:37 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=A0=E5=85=A5=E7=99=BB=E5=BD=95=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E5=92=8C=E7=A7=BB=E9=99=A4=E4=B8=8B=E7=BA=BF=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E5=92=8C=E8=81=8A=E5=A4=A9=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CC3.1.py | 239 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ CS3.1.py | 8 +- 2 files changed, 243 insertions(+), 4 deletions(-) create mode 100644 CC3.1.py diff --git a/CC3.1.py b/CC3.1.py new file mode 100644 index 0000000..438a1a4 --- /dev/null +++ b/CC3.1.py @@ -0,0 +1,239 @@ +import tkinter as tk +import socket +import json +import threading +import queue +from tkinter import scrolledtext, messagebox + +class ChatClient: + def __init__(self, root): + self.root = root + self.root.title("聊天客户端") + self.socket = None + self.connected = False + self.username = None + self.message_queue = queue.Queue() + self.network_thread = None + + self.setup_ui() + self.check_messages() + + def setup_ui(self): + self.login_frame = tk.Frame(self.root) + self.login_frame.pack(pady=10) + + tk.Label(self.login_frame, text="用户名:").grid(row=0, column=0) + self.username_entry = tk.Entry(self.login_frame) + self.username_entry.grid(row=0, column=1) + + tk.Label(self.login_frame, text="密码:").grid(row=1, column=0) + self.password_entry = tk.Entry(self.login_frame, show="*") + self.password_entry.grid(row=1, column=1) + + self.login_btn = tk.Button(self.login_frame, text="登录", command=self.start_login) + self.login_btn.grid(row=2, column=0, pady=5) + + self.register_btn = tk.Button(self.login_frame, text="注册", command=self.start_register) + self.register_btn.grid(row=2, column=1, pady=5) + + self.chat_frame = tk.Frame(self.root) + + self.chat_history = scrolledtext.ScrolledText(self.chat_frame, state='disabled') + self.chat_history.pack(pady=5, padx=5, fill=tk.BOTH, expand=True) + + self.message_entry = tk.Entry(self.chat_frame) + self.message_entry.pack(pady=5, padx=5, fill=tk.X) + + self.send_btn = tk.Button(self.chat_frame, text="发送", command=self.send_message) + self.send_btn.pack(pady=5) + + def check_messages(self): + try: + while True: + msg_type, data = self.message_queue.get_nowait() + if msg_type == "login_result": + self.handle_login_result(data) + elif msg_type == "register_result": + self.handle_register_result(data) + elif msg_type == "chat_message": + self.display_message(data) + elif msg_type == "error": + messagebox.showerror("错误", data) + elif msg_type == "disconnect": + self.handle_disconnect() + except queue.Empty: + pass + finally: + self.root.after(100, self.check_messages) + + def start_network_thread(self, task, *args): + if self.network_thread and self.network_thread.is_alive(): + return False + + self.network_thread = threading.Thread( + target=task, + args=args, + daemon=True + ) + self.network_thread.start() + return True + + def start_login(self): + if not self.start_network_thread(self.perform_login): + messagebox.showwarning("警告", "已有操作正在进行") + + def start_register(self): + if not self.start_network_thread(self.perform_register): + messagebox.showwarning("警告", "已有操作正在进行") + + def perform_login(self): + try: + username = self.username_entry.get() + password = self.password_entry.get() + + if not username or not password: + self.message_queue.put(("error", "用户名和密码不能为空")) + return + + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.settimeout(5) + try: + sock.connect(("localhost", 8888)) + sock.settimeout(10) + + sock.sendall(json.dumps({ + "type": "login", + "username": username, + "password": password + }).encode()) + + response = sock.recv(1024) + if not response: + self.message_queue.put(("error", "服务器无响应")) + return + + result = json.loads(response.decode()) + self.message_queue.put(("login_result", (result, sock))) + except socket.timeout: + self.message_queue.put(("error", "连接超时")) + except Exception as e: + self.message_queue.put(("error", f"登录错误: {str(e)}")) + if sock: + sock.close() + except Exception as e: + self.message_queue.put(("error", f"系统错误: {str(e)}")) + + def perform_register(self): + try: + username = self.username_entry.get() + password = self.password_entry.get() + + if not username or not password: + self.message_queue.put(("error", "用户名和密码不能为空")) + return + + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.settimeout(5) + try: + sock.connect(("localhost", 8888)) + sock.settimeout(10) + + sock.sendall(json.dumps({ + "type": "register", + "username": username, + "password": password + }).encode()) + + response = sock.recv(1024) + if not response: + self.message_queue.put(("error", "服务器无响应")) + return + + result = json.loads(response.decode()) + self.message_queue.put(("register_result", result)) + except socket.timeout: + self.message_queue.put(("error", "连接超时")) + except Exception as e: + self.message_queue.put(("error", f"注册错误: {str(e)}")) + finally: + if sock: + sock.close() + except Exception as e: + self.message_queue.put(("error", f"系统错误: {str(e)}")) + + def handle_login_result(self, data): + result, sock = data + if result.get("status") == "success": + self.socket = sock + self.connected = True + self.username = self.username_entry.get() + self.login_frame.pack_forget() + self.chat_frame.pack(fill=tk.BOTH, expand=True) + threading.Thread(target=self.receive_messages, daemon=True).start() + else: + self.message_queue.put(("error", result.get("message", "登录失败"))) + if sock: + sock.close() + + def handle_register_result(self, result): + if result.get("success"): + messagebox.showinfo("注册成功", "账号注册成功,请登录") + else: + self.message_queue.put(("error", result.get("message", "注册失败"))) + + def send_message(self): + message = self.message_entry.get() + if not message or not self.connected: + return + + try: + self.socket.sendall(json.dumps({ + "type": "chat", + "message": message + }).encode()) + self.message_entry.delete(0, tk.END) + except Exception as e: + self.message_queue.put(("error", f"发送消息失败: {str(e)}")) + self.connected = False + self.message_queue.put(("disconnect", None)) + + def receive_messages(self): + while self.connected: + try: + data = self.socket.recv(1024) + if not data: + break + + message = json.loads(data.decode()) + self.message_queue.put(("chat_message", message)) + except: + break + + self.connected = False + self.message_queue.put(("disconnect", None)) + + def display_message(self, message): + self.chat_history.config(state='normal') + self.chat_history.insert(tk.END, f"{message.get('user', '系统')}: {message.get('message')}\n") + self.chat_history.config(state='disabled') + self.chat_history.see(tk.END) + + def handle_disconnect(self): + if self.connected: + self.socket.close() + self.connected = False + self.chat_frame.pack_forget() + self.login_frame.pack(pady=10) + messagebox.showinfo("断开连接", "与服务器的连接已断开") + + def on_closing(self): + if self.connected and self.socket: + self.socket.close() + self.root.destroy() + +if __name__ == "__main__": + root = tk.Tk() + root.geometry("500x400") + client = ChatClient(root) + root.protocol("WM_DELETE_WINDOW", client.on_closing) + root.mainloop() \ No newline at end of file diff --git a/CS3.1.py b/CS3.1.py index ecfff95..a819a37 100644 --- a/CS3.1.py +++ b/CS3.1.py @@ -1,4 +1,3 @@ - import threading import json from flask import Flask, jsonify, request @@ -7,6 +6,7 @@ import socket app = Flask(__name__) socket_server = socket.socket() +socket_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) socket_server.bind(("localhost", 8888)) active_users = {} chat_connections = [] @@ -95,7 +95,7 @@ def handle_socket_message(data, addr, conn): active_users[addr[0]] = data['username'] chat_connections.append(conn) return {"status": "success", "message": "Login successful"} - return {"success": "error", "message": "Invalid credentials"} + return {"status": "error", "message": "Invalid credentials"} elif action == 'chat': if addr[0] in active_users: message = { @@ -129,7 +129,7 @@ def run_socket_server(): conn.sendall(json.dumps(response).encode()) except json.JSONDecodeError: conn.sendall(json.dumps( - {"success": "error", "message": "Invalid JSON"} + {"status": "error", "message": "Invalid JSON"} ).encode()) except ConnectionResetError: if addr[0] in active_users: @@ -145,4 +145,4 @@ if __name__ == '__main__': with get_db_connection() as conn: conn.execute('''CREATE TABLE IF NOT EXISTS users (name TEXT, passwd TEXT)''') - app.run(port=5001) + app.run(port=5001) \ No newline at end of file