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("127.0.0.1", 5555)
server.start()
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("127.0.0.1", 5555)
chat_window = ChatWindow(client)
if chat_window.username:
chat_window.mainloop()
为什么当有一个客户端连接了服务器,再次连接一个客户端,第二个客户端发的信息只能看到信息,看不到用户名,怎么修改
在handle_client方法中,你需要将接收到的消息和用户名一起发送,使得客户端能够在接收到消息后同时看到用户名。修改handle_client方法如下:
def handle_client(self, client):
while True:
try:
message = client.recv(1024)
if message:
username = self.clients[client]
message_with_username = f"{username}: {message.decode('utf-8')}"
self.broadcast(message_with_username.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
当客户端发送消息时,需要将消息和用户名一起发送,例如:
def send_message(self):
message = f"{self.username}: {self.entry.get()}\n"
self.entry.delete(0, tk.END)
self.client.send(message.encode('utf-8'))
这样做就可以同时显示用户名和消息了。
大哥
def send_message(self):
message = f"{self.username}: {self.entry.get()}\n"
self.entry.delete(0, tk.END)
self.client.send(message.encode('utf-8'))
这个是修改的上面的send_message还是下面的send_message,如果是下面的send_message,那个entry的问题怎么解决?这个引起报错了
@难亦: 改下面的send_message(当客户端发送消息时,需要将消息和用户名一起发送),回答了都不看字,报错就调试一下,先把报错的代码去掉,让它能运行,这个完全盲写的代码只是说个意思,你改出的代码能符合需求就行
在提供的代码中,当第二个客户端连接并发送消息时,只会在聊天窗口中显示消息文本,而没有显示用户名。这是因为在ChatWindow类的display_received_message方法中,只是简单地将消息文本追加到聊天窗口中,而没有包含用户名。
要修改代码以显示用户名和消息,可以在接收到消息后,将用户名和消息文本一起显示。以下是对display_received_message方法的修改:
python
Copy code
def display_received_message(self, message):
username, message_text = message.split(": ", 1) # 解析出用户名和消息文本
display_message = f"{username}: {message_text}"
self.chat_text.config(state=tk.NORMAL)
self.chat_text.insert(tk.END, display_message + "\n")
self.chat_text.config(state=tk.DISABLED)
这样修改后,当收到消息时,会从消息文本中解析出用户名和实际消息,然后将它们一起显示在聊天窗口中。
请注意,上述修改假设消息文本的格式为“用户名: 消息”。如果实际情况有所不同,你需要根据消息文本的格式进行相应的解析修改。
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, username))
thread.start()
else:
client.send("USERNAME_TAKEN".encode("utf-8"))
client.close()
def handle_client(self, client, username):
while True:
try:
message = client.recv(1024)
if message:
self.broadcast(f"{username}: {message.decode('utf-8')}".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
def broadcast(self, message, sender=None):
for client in self.clients:
if client != sender:
client.send(message)
if name == "main":
server = Server("127.0.0.1", 15555)
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.client.close()
self.destroy()
if name == "main":
client = Client("127.0.0.1", 15555)
chat_window = ChatWindow(client)
if chat_window.username:
chat_window.mainloop()