为什么当有一个客户端连接了服务器,再次连接一个客户端,第二个客户端发的信息只能看到信息,看不到用户名

为什么当有一个客户端连接了服务器,再次连接一个客户端,第二个客户端发的信息只能看到信息,看不到用户名,怎么修改?




# server文件:
import socket
import threading


class Server:
    def __init__(self, host, port):
        self.host = host
        self.port = port
        self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server.bind((self.host, self.port))
        self.clients = {}
        self.usernames = []

    def start(self):
        self.server.listen()
        print(f"Server started on {self.host}:{self.port}")
        while True:
            client, addr = self.server.accept()
            client.send("USERNAME".encode("utf-8"))
            username = client.recv(1024).decode("utf-8")
            if username not in self.usernames:
                self.usernames.append(username)
                self.clients[client] = username
                print(f"Connected: {addr}, Username: {username}")
                self.broadcast(f"{username} joined the chat!".encode("utf-8"))
                thread = threading.Thread(target=self.handle_client, args=(client,))
                thread.start()
            else:
                client.send("USERNAME_TAKEN".encode("utf-8"))
                client.close()

    def handle_client(self, client):
        while True:
            try:
                message = client.recv(1024)
                if message:
                    self.broadcast(message, client)
            except Exception as e:
                print(f"Error: {e}")
                username = self.clients[client]
                self.usernames.remove(username)
                del self.clients[client]
                client.close()
                self.broadcast(f"{username} left the chat!".encode("utf-8"))
                break

    def broadcast(self, message, sender=None):
        for client in self.clients:
            if client != sender:
                client.send(message)


if __name__ == "__main__":
    server = Server("10.41.38.122", 5555)
    server.start()


# client文件:
import socket
import threading
import tkinter as tk
from tkinter import simpledialog

class Client:
    def __init__(self, host, port):
        self.host = host
        self.port = port
        self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.client.connect((self.host, self.port))

    def send_message(self, message):
        self.client.send(message.encode("utf-8"))

    def receive_messages(self, callback):
        while True:
            try:
                message = self.client.recv(1024).decode("utf-8")
                if message:
                    callback(message)
            except Exception as e:
                print(f"Error: {e}")
                self.client.close()
                break

class ChatWindow(tk.Tk):
    def __init__(self, client):
        super().__init__()
        self.client = client
        self.title("Chat Room")
        self.geometry("500x400")

        self.chat_text = tk.Text(self, wrap=tk.WORD)
        self.chat_text.pack(padx=5, pady=5, fill=tk.BOTH, expand=True)
        self.chat_text.config(state=tk.DISABLED)

        self.entry_frame = tk.Frame(self)
        self.entry_frame.pack(padx=5, pady=5, fill=tk.X)

        self.message_entry = tk.Entry(self.entry_frame)
        self.message_entry.pack(side=tk.LEFT, fill=tk.X, expand=True)

        self.send_button = tk.Button(self.entry_frame, text="Send", command=self.send_message)
        self.send_button.pack(side=tk.RIGHT)

        self.protocol("WM_DELETE_WINDOW", self.close)

        self.username = self.get_username()
        if self.username:
            self.client.send_message(self.username)
            thread = threading.Thread(target=self.client.receive_messages, args=(self.display_received_message,))
            thread.start()
        else:
            self.close()

    def get_username(self):
        username = tk.simpledialog.askstring("Username", "Enter your username:", parent=self)
        return username

    def send_message(self):
        message = self.message_entry.get()
        if message:
            self.client.send_message(message)
            self.display_received_message(f"{self.username}: {message}")
            self.message_entry.delete(0, tk.END)

    def display_received_message(self, message):
        self.chat_text.config(state=tk.NORMAL)
        self.chat_text.insert(tk.END, message + "\n")
        self.chat_text.config(state=tk.DISABLED)

    def close(self):
        self.client.send_message("/quit")
        self.client.client.close()
        self.destroy()

if __name__ == "__main__":
    client = Client("10.41.38.122", 5555)
    chat_window = ChatWindow(client)
    if chat_window.username:
        chat_window.mainloop()


当第二个客户端连接到服务器时,它会发送消息,但消息中只包含文本内容,没有包含用户名。这是因为您的客户端代码在发送消息时,只发送了消息的文本内容,没有包含用户名信息。要解决这个问题,您可以修改客户端代码,在发送消息时同时发送用户名信息。

具体来说,您可以在客户端的send_message方法中,将消息和用户名一起发送,例如:

def send_message(self, message):
    username_message = self.username + ": " + message
    self.client.send(username_message.encode("utf-8"))

这样,当客户端发送消息时,消息中就包含了用户名和文本内容。在服务器端接收到这个消息后,就可以正确地显示用户名和消息内容了。

同时,您需要在服务器端的handle_client方法中,将接收到的消息分解成用户名和文本内容,例如:

python
Copy


def handle_client(self, client):
    while True:
        try:
            message = client.recv(1024).decode("utf-8")
            if message:
                username, text = message.split(": ")
                self.broadcast(f"{username}: {text}".encode("utf-8"), client)
        except Exception as e,print(f"Error: {e}")
            username = self.clients[client]
            self.usernames.remove(username)
            del self.clients[client]
            client.close()
            self.broadcast(f"{username} left the chat!".encode("utf-8"))
            break

这样,服务器端就可以正确地处理包含用户名信息的消息,并将用户名和消息内容一起广播给所有客户端了。

不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^