当前位置: 代码网 > it编程>前端脚本>Python > 基于Python实现多人聊天室的示例代码

基于Python实现多人聊天室的示例代码

2025年02月20日 Python 我要评论
本文主要为大家介绍一下如何实现一个多人聊天室(server+client),感兴趣的小伙伴可以了解下效果图通过本地服务器以用户名登录实现关键代码支持群聊和私聊sever端代码:import socke

本文主要为大家介绍一下如何实现一个多人聊天室(server+client),感兴趣的小伙伴可以了解下

效果图

通过本地服务器以用户名登录

实现关键代码

支持群聊和私聊

sever端代码:

import socket
import threading
from datetime import datetime
from collections import ordereddict
 
class chatserver:
    def __init__(self, host='0.0.0.0', port=50000):
        self.clients = ordereddict()
        self.server = socket.socket(socket.af_inet, socket.sock_stream)
        self.server.setsockopt(socket.sol_socket, socket.so_reuseaddr, 1)
        self.server.bind((host, port))
        self.server.listen(5)
        print(f"🟢 服务端已启动在 {host}:{port}")
 
    def handle_client(self, conn, addr):
        username = none
        try:
            username = conn.recv(1024).decode().strip()
            if not username or username in self.clients:
                conn.send("username_invalid".encode())
                conn.close()
                return
 
            conn.send("connect_success".encode())
            self.clients[username] = conn
            self.broadcast_system_msg(f"🚩 {username} 进入聊天室")
            self.broadcast_userlist()
 
            while true:
                try:
                    data = conn.recv(4096)
                    if not data: break
                    
                    msg = data.decode().strip()
                    if msg == "heartbeat":
                        conn.send(b"heartbeat_ack")
                    elif msg.startswith("@@"):
                        target, _, content = msg[2:].partition(' ')
                        self.handle_private(username, target, content)
                    else:
                        self.broadcast_msg(f"{username}:{msg}")
 
                except exception as e:
                    print(f"处理错误:{str(e)}")
                    break
 
        except connectionreseterror:
            print(f"❌ {username} 异常断开")
        finally:
            if username in self.clients:
                del self.clients[username]
                self.broadcast_system_msg(f"🚩 {username} 离开聊天室")
                self.broadcast_userlist()
            conn.close()
 
    def handle_private(self, sender, target, content):
        if target in self.clients:
            timestamp = datetime.now().strftime("%h:%m:%s")
            msg = f"[{timestamp}] [私聊] {sender} -> 你:{content}"
            self.clients[target].send(msg.encode())
            self.clients[sender].send(msg.encode())
        else:
            self.clients[sender].send(f"用户 {target} 不在线".encode())
 
    def broadcast_msg(self, msg):
        timestamp = datetime.now().strftime("%h:%m:%s")
        full_msg = f"[{timestamp}] {msg}\n"
        for client in self.clients.values():
            try: client.send(full_msg.encode())
            except: pass
 
    def broadcast_system_msg(self, msg):
        full_msg = f"system:{msg}\n"
        for client in self.clients.values():
            try: client.send(full_msg.encode())
            except: pass
 
    def broadcast_userlist(self):
        user_list = ",".join(self.clients.keys())
        msg = f"userlist:{user_list}\n"
        for client in self.clients.values():
            try: client.send(msg.encode())
            except: pass
 
    def start(self):
        while true:
            conn, addr = self.server.accept()
            threading.thread(target=self.handle_client, args=(conn, addr)).start()
 
if __name__ == "__main__":
    chatserver().start() 

客户端代码:

import tkinter as tk
from tkinter import ttk, scrolledtext, messagebox
import socket
import threading
 
class chatclient:
    def __init__(self, master):
        self.master = master
        self.client_socket = none
        self.username = ""
        self.running = false
        
        master.title("在线聊天室")
        master.geometry("900x600")
        self.create_widgets()
        self.show_login_dialog()
 
    def create_widgets(self):
        self.user_frame = ttk.frame(self.master, width=200)
        self.user_frame.pack(side=tk.left, fill=tk.y)
        
        self.user_list = ttk.treeview(self.user_frame, show="tree", selectmode='browse')
        self.user_list.pack(expand=true, fill=tk.both)
        self.user_list.bind('<<treeviewselect>>', self.select_user)
 
        self.chat_frame = ttk.frame(self.master)
        self.chat_frame.pack(expand=true, fill=tk.both)
        
        self.chat_area = scrolledtext.scrolledtext(self.chat_frame, state=tk.disabled)
        self.chat_area.pack(expand=true, fill=tk.both)
        
        # 输入框和按钮框架
        input_frame = ttk.frame(self.chat_frame)
        input_frame.pack(fill=tk.x, pady=5)
        
        self.msg_entry = ttk.entry(input_frame)
        self.msg_entry.pack(side=tk.left, expand=true, fill=tk.x)
        self.msg_entry.bind("<return>", self.send_message)
        
        # 添加发送按钮
        send_btn = ttk.button(input_frame, text="发送", command=self.send_message)
        send_btn.pack(side=tk.right, padx=5)
 
    def select_user(self, event):
        selected = self.user_list.selection()
        if selected:
            target = self.user_list.item(selected[0])['text']
            current = self.msg_entry.get()
            self.msg_entry.delete(0, tk.end)
            self.msg_entry.insert(0, f"@@{target} " if not current.startswith("@") else "")
 
    def show_login_dialog(self):
        self.login_dialog = tk.toplevel(self.master)
        self.login_dialog.title("登录")
        
        ttk.label(self.login_dialog, text="服务器地址:").grid(row=0, column=0, padx=5, pady=5)
        self.server_entry = ttk.entry(self.login_dialog)
        self.server_entry.insert(0, "127.0.0.1")
        self.server_entry.grid(row=0, column=1, padx=5, pady=5)
 
        ttk.label(self.login_dialog, text="端口号:").grid(row=1, column=0, padx=5, pady=5)
        self.port_entry = ttk.entry(self.login_dialog)
        self.port_entry.insert(0, "50000")
        self.port_entry.grid(row=1, column=1, padx=5, pady=5)
 
        ttk.label(self.login_dialog, text="用户名:").grid(row=2, column=0, padx=5, pady=5)
        self.username_entry = ttk.entry(self.login_dialog)
        self.username_entry.grid(row=2, column=1, padx=5, pady=5)
 
        ttk.button(self.login_dialog, text="登录", command=self.connect_server).grid(row=3, columnspan=2, pady=10)
 
    def connect_server(self):
        server = self.server_entry.get()
        port = self.port_entry.get()
        self.username = self.username_entry.get().strip()
 
        if not self.username:
            messagebox.showerror("错误", "用户名不能为空")
            return
 
        try:
            self.client_socket = socket.socket(socket.af_inet, socket.sock_stream)
            self.client_socket.connect((server, int(port)))
            self.client_socket.send(self.username.encode())
            
            response = self.client_socket.recv(1024).decode()
            if response != "connect_success":
                messagebox.showerror("错误", f"连接失败: {response}")
                return
 
            self.running = true
            self.login_dialog.destroy()
            self.master.title(f"在线聊天室 - {self.username}")
            threading.thread(target=self.receive_messages, daemon=true).start()
 
        except exception as e:
            messagebox.showerror("连接失败", str(e))
            if self.client_socket:
                self.client_socket.close()
 
    def receive_messages(self):
        buffer = ""
        while self.running:
            try:
                data = self.client_socket.recv(4096)
                if not data: break
                
                buffer += data.decode()
                while "\n" in buffer:
                    msg, buffer = buffer.split("\n", 1)
                    if msg.startswith("userlist:"):
                        self.update_user_list(msg[9:].split(','))
                    elif msg.startswith("system:"):
                        self.display_system_msg(msg[7:])
                    else:
                        self.display_message(msg)
            except:
                break
 
    def update_user_list(self, users):
        current = set(self.user_list.get_children())
        online = set(users)
        
        for user in current - online:
            self.user_list.delete(user)
        
        for user in online - current:
            self.user_list.insert("", "end", iid=user, text=user)
 
    def display_message(self, msg):
        self.chat_area.config(state=tk.normal)
        self.chat_area.insert(tk.end, msg + "\n")
        self.chat_area.see(tk.end)
        self.chat_area.config(state=tk.disabled)
 
    def display_system_msg(self, msg):
        self.chat_area.config(state=tk.normal)
        self.chat_area.insert(tk.end, f"【系统】{msg}\n", 'system')
        self.chat_area.see(tk.end)
        self.chat_area.config(state=tk.disabled)
 
    def send_message(self, event=none):
        msg = self.msg_entry.get().strip()
        if msg:
            try:
                self.client_socket.send(f"{msg}\n".encode())
                self.msg_entry.delete(0, tk.end)
                if msg.startswith("@@"):
                    self.display_message(f"[我] 私聊 {msg[2:].split(' ')[0]}:{' '.join(msg.split()[1:])}")
                else:
                    self.display_message(f"[我]:{msg}")
            except exception as e:
                messagebox.showerror("发送失败", str(e))
 
if __name__ == "__main__":
    root = tk.tk()
    app = chatclient(root)
    root.mainloop() 

以上就是基于python实现多人聊天室的示例代码的详细内容,更多关于python多人聊天室的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com