重温本章完成的QQ客户机/服务器设计,改进客户机与服务器设计,双击用户列表中的某一用户,打开一个新的一对一聊天界面,实现私聊功能。
时间: 2024-05-13 07:19:12 浏览: 14
好的,我们可以进行以下步骤来完成这个改进:
1. 在客户端的用户列表中,添加一个双击用户的事件处理函数。
2. 在事件处理函数中,向服务器发送一个私聊请求,携带对方用户的ID。
3. 服务器接收到私聊请求后,向目标用户发送一个私聊请求通知。
4. 目标用户接收到私聊请求后,向服务器发送一个确认私聊请求的消息。
5. 服务器接收到确认消息后,向两个用户分别发送一个私聊开始的通知。
6. 客户端接收到私聊开始的通知后,打开一个新的一对一聊天界面,与目标用户进行私聊。
注意,为了实现私聊功能,我们需要在服务器端维护每个用户之间的私聊状态,并且为每个私聊会话分配一个唯一的会话ID。在客户端,我们需要为每个私聊会话创建一个对应的聊天界面,并在界面中显示私聊的内容。
下面是一个简单的代码示例,仅供参考:
客户端代码:
```
import socket
import tkinter as tk
class Client:
def __init__(self, host, port):
self.host = host
self.port = port
self.sock = socket.socket()
self.root = tk.Tk()
self.user_list = tk.Listbox(self.root)
self.chat_boxes = {}
self.user_list.bind('<Double-Button-1>', self.on_user_double_click)
self.user_list.pack()
self.root.mainloop()
def on_user_double_click(self, event):
user_id = self.user_list.get(self.user_list.curselection())
self.sock.send(f"PRIVATE_CHAT_REQUEST:{user_id}".encode())
def receive_messages(self):
while True:
data = self.sock.recv(1024).decode()
if not data:
break
if data.startswith("PRIVATE_CHAT_START"):
session_id, user_id = data.split(':')[1:]
self.open_chat_box(session_id, user_id)
elif data.startswith("PRIVATE_CHAT_MESSAGE"):
session_id, message = data.split(':')[1:]
if session_id in self.chat_boxes:
self.chat_boxes[session_id].show_message(message)
def open_chat_box(self, session_id, user_id):
chat_box = ChatBox(self.sock, session_id, user_id)
self.chat_boxes[session_id] = chat_box
chat_box.show()
class ChatBox:
def __init__(self, sock, session_id, user_id):
self.sock = sock
self.session_id = session_id
self.user_id = user_id
self.root = tk.Toplevel()
self.message_list = tk.Listbox(self.root)
self.message_entry = tk.Entry(self.root)
self.message_entry.bind('<Return>', self.on_message_entry)
self.message_list.pack()
self.message_entry.pack()
def show(self):
self.root.title(f"Private Chat with {self.user_id}")
self.root.mainloop()
def on_message_entry(self, event):
message = self.message_entry.get()
self.sock.send(f"PRIVATE_CHAT_MESSAGE:{self.session_id}:{message}".encode())
self.show_message(f"You: {message}")
self.message_entry.delete(0, tk.END)
def show_message(self, message):
self.message_list.insert(tk.END, message)
Client('localhost', 8000)
```
服务器端代码:
```
import socket
import threading
class Server:
def __init__(self, host, port):
self.host = host
self.port = port
self.users = {}
self.sessions = {}
self.sock = socket.socket()
self.sock.bind((self.host, self.port))
self.sock.listen(5)
print(f"Listening on {self.host}:{self.port}")
self.accept_connections()
def accept_connections(self):
while True:
client_sock, client_addr = self.sock.accept()
print(f"Accepted connection from {client_addr}")
threading.Thread(target=self.handle_client, args=(client_sock,)).start()
def handle_client(self, client_sock):
user_id = client_sock.recv(1024).decode()
self.users[user_id] = client_sock
print(f"User {user_id} connected")
while True:
data = client_sock.recv(1024).decode()
if not data:
break
if data.startswith("PRIVATE_CHAT_REQUEST"):
target_user_id = data.split(':')[1]
session_id = self.create_session(user_id, target_user_id)
self.send_private_chat_request(target_user_id, session_id, user_id)
elif data.startswith("PRIVATE_CHAT_MESSAGE"):
session_id, message = data.split(':')[1:]
self.send_private_chat_message(session_id, user_id, message)
del self.users[user_id]
self.close_sessions(user_id)
client_sock.close()
print(f"User {user_id} disconnected")
def create_session(self, user1_id, user2_id):
session_id = f"{user1_id}-{user2_id}"
self.sessions[session_id] = [user1_id, user2_id]
return session_id
def close_session(self, session_id):
del self.sessions[session_id]
def close_sessions(self, user_id):
for session_id, users in self.sessions.items():
if user_id in users:
self.close_session(session_id)
def send_private_chat_request(self, target_user_id, session_id, user_id):
target_sock = self.users[target_user_id]
target_sock.send(f"PRIVATE_CHAT_START:{session_id}:{user_id}".encode())
def send_private_chat_message(self, session_id, user_id, message):
users = self.sessions.get(session_id, [])
for target_user_id in users:
if target_user_id != user_id:
target_sock = self.users.get(target_user_id)
if target_sock:
target_sock.send(f"PRIVATE_CHAT_MESSAGE:{session_id}:{user_id}:{message}".encode())
Server('localhost', 8000)
```
当用户双击用户列表中的某个用户时,客户端会向服务器发送一个私聊请求,携带目标用户ID。服务器接收到私聊请求后,会创建一个私聊会话,并向目标用户发送一个私聊请求通知。目标用户接收到私聊请求后,会弹出一个对话框,询问是否同意私聊。如果目标用户同意私聊,则会向服务器发送一个确认私聊请求的消息。服务器接收到确认消息后,会向两个用户分别发送一个私聊开始的通知。客户端接收到私聊开始的通知后,会打开一个新的一对一聊天界面,与目标用户进行私聊。在私聊会话中,用户可以发送文本消息,并且会即时显示在聊天界面中。