使用tkinter和socket完成多人聊天室

登陆界面
选择聊天室(私人聊天室,公共聊天室,只写了公共聊天室一部分,私人聊天室懒得写了)
聊天室界面

客户端

import  threading
from tkinter import *
class tcpclient():
    def __init__(self):
        self.Host = 'localhost'
        self.Port = 21567
        self.BUFSIZ = 1024
        self.ADDR = (self.Host, self.Port)
        self.tcpsock = socket(AF_INET, SOCK_STREAM)
        self.tcpsock.connect(self.ADDR)
        self.top1=Tk()
        self.label_name=Label(self.top1,text='username')
        self.top1.geometry('300x300')
        self.label_name.place(x=10,y=70,width=70,height=40)
        self.entry = Entry(self.top1, width=25)
        self.entry.place(x=80, y=70, height=40, width=200)
        self.buton = Button(self.top1, text='登陆',command=self.login_in)
        self.buton.place(x=200, y=150, width=60, height=30)
        self.top1.mainloop()
    #登陆界面
    def login_in(self):
        text=self.entry.get()#输入用户名
        self.tcpsock.send(text.encode('utf-8'))
        self.top1.destroy()
        self.top2=Tk()#选择聊天室
        self.top2.geometry('300x300')
        self.private=Button(self.top2,text='private room')#私人聊天室
        self.private.place(x=30,y=100,width=100,height=100)
        self.public=Button(self.top2,text='public room',command=self.public_room)#公共聊天室
        self.public.place(x=170,y=100,width=100,height=100)
        self.top2.mainloop()
    #进入聊天室界面
    def public_room(self):
        self.top2.destroy()
        #发送进入公共聊天室请求
        self.tcpsock.send('public'.encode())
        self.top3=Tk()
        self.top3.geometry('300x400')
        self.top3.title('public room')
        self.frame1=Frame(self.top3,bg='red')
        self.textlist=Text(self.frame1)#聊天记录框
        self.textlist.pack()
        self.frame1.place(x=10,y=10,width=270)
        self.text_input=Text(self.top3,bg='white')#消息输入框
        self.text_input.place(x=10,y=250,height=100,width=270)
        self.send_button=Button(self.top3,text='send',command=self.send_massage)#发送按钮
        self.send_button.place(x=250,y=370)
        threading.Thread(target=self.rec_message, args=()).start()
        self.top3.mainloop()
    #发送消息
    def send_massage(self):
        self.massage=self.text_input.get('0.0','end')
        self.tcpsock.send(self.massage.encode('utf-8'))
        data='I:'+self.massage
        self.textlist.insert(END, data,)
        self.textlist.config(fg='red')
        self.text_input.delete('0.0','end')
    #接收消息并显示
    def rec_message(self):
        while True:
            try:
                self.data=self.tcpsock.recv(self.BUFSIZ).decode('utf-8')
                self.textlist.insert(END,self.data,)
                self.textlist.config(fg='blue')
            except ConnectionError:
                print('error')
if __name__ == '__main__':
    a=tcpclient()

服务器

from socket import *
import threading
import time

class tcpserve():
    def __init__(self):
        self.Host=''
        self.Port=21567
        self.BUFSIZ=1024
        self.ADDR=(self.Host,self.Port)
        self.tcpsock=socket(AF_INET,SOCK_STREAM)
        self.tcpsock.bind(self.ADDR)
        self.tcpsock.listen(5)
        self.doubleclients={}#群聊接入的客户列表
        self.singleclient={}#私人聊天室客户表
        self.client_socket={}#客户对应的嵌套字
        print('waiting for connection')
        self.tcp,self.addr=self.tcpsock.accept()
        print('connect from :',self.addr)
        self.usename=self.tcp.recv(self.BUFSIZ).decode('utf-8')
    def Deal(self,tcp,usename):

        data=tcp.recv(self.BUFSIZ).decode()
        if data=='public':
            #群聊
            while True:
                massage=tcp.recv(self.BUFSIZ).decode()
                #退出指令
                if massage=='quit':
                    del self.doubleclients[usename]
                    tcp.close()
                else:
                    for client in self.doubleclients:
                        self.doubleclients[client].send(('[%s] %s:%s'%(time.strftime('%Y/%m/%d %H:%M:%S',time.localtime()),usename,massage)).encode('utf-8'))
if __name__ == '__main__':
    tcpse=tcpserve()
    if not tcpse.doubleclients.__contains__(tcpse .usename):
        tcpse .doubleclients[tcpse.usename] = tcpse.tcp
        chat = threading.Thread(target=tcpse.Deal, args=(tcpse.tcp, tcpse.usename))
        chat.start()
    else:
        print('user is onlion')

渣渣GUI,见谅
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python Socket是Python编程语言标准库的一部分,用于网络通信,在Python socket中实现多人聊天室需要以下步骤: 1. 创建一个服务器Socket和一个客户端Socket,分别负责监听和连接。 2. 在服务器端设置一个线程或进程,负责监听所有连接并接受任何来自客户端的消息。在客户端端设置一个线程或进程,负责发送消息和接收来自服务器的消息。 3. 建立一个数据结构保存所有连接的客户端套接字,以及每个客户端的IP地址和端口号。 4. 实现好友聊天和群聊功能,对于需要多个接收者的消息组合来发送,并在每个接收者的客户端显示消息。 5. 实现图片和表情功能,将图像数据编码为字节流并将其发送到所有客户端。 6. 实现文件传输功能,将文件分成小块并逐个发送,以便所有客户端都能够接收到。 示例代码如下: server.py: import socket import threading # 设置主机和端口号 host = "127.0.0.1" port = 9999 # 创建Socket实例并监听端口号 server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind((host, port)) server.listen() # 保存所有连接的客户端 clients = [] def broadcast(message): """ 向所有客户端广播消息 """ for client in clients: client.send(message) def handle_client(client): """ 处理客户端消息 """ while True: try: message = client.recv(1024) broadcast(message) except: index = clients.index(client) clients.remove(client) client.close() nickname = nicknames[index] broadcast(f"{nickname}离开聊天室!".encode("utf-8")) nicknames.remove(nickname) break def receive(): """ 监听所有连接,接受客户端信息 """ while True: client, address = server.accept() print(f"已连接到:{str(address)}") # 保存客户端套接字和昵称 client.send("请输入昵称:".encode("utf-8")) nickname = client.recv(1024).decode("utf-8") nicknames.append(nickname) clients.append(client) # 输出已连接客户端昵称 print(f"昵称:{nickname}") broadcast(f"{nickname}加入聊天室!".encode("utf-8")) client.send("已成功连接到聊天室!".encode("utf-8")) # 创建新线程处理该客户端 thread = threading.Thread(target=handle_client, args=(client,)) thread.start() if __name__ == "__main__": print("聊天室服务器已开启,请等待连接!") receive() client.py: import socket import threading import tkinter from tkinter import ttk, scrolledtext, messagebox from tkinter.filedialog import askopenfilename from PIL import Image, ImageTk import os nickname = "" s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) def receive(): """ 接受服务端消息 """ while True: try: message = s.recv(1024).decode("utf-8") if message == "请输入昵称:": s.send(nickname.encode("utf-8")) else: print(message) add_to_chat(message) except: print("发生错误!") s.close() break def send(event=None): """ 发送消息到服务器 """ message = my_msg.get() if message != "": s.send(message.encode("utf-8")) my_msg.set("") if message == "{quit}": s.close() root.quit() def add_to_chat(message): """ 在聊天室窗口中添加新消息 """ chat_box.configure(state="normal") chat_box.insert("end", message + "\n") chat_box.configure(state="disabled") chat_box.see("end") def choose_file(): """ 弹出对话框选择文件 """ file = askopenfilename() if file: filename = os.path.basename(file) add_to_chat(f"{nickname}发送了文件:{filename}") filesize = os.path.getsize(file) # 发送文件头信息 s.send(f"FILE {filename} {filesize}".encode("utf-8")) # 分块发送文件 with open(file, "rb") as f: while True: data = f.read(1024) if not data: break s.sendall(data) def choose_image(): """ 弹出对话框选择图片 """ file = askopenfilename() if file: image = Image.open(file) photo = ImageTk.PhotoImage(image) chat_box.image_create("end", image=photo) # 发送图像数据 with open(file, "rb") as f: bytes_img = f.read() s.sendall(bytes_img) def init_send_frame(): """ 创建发送消息区域 """ send_frame = ttk.Frame(root) send_frame.pack(fill="x") global my_msg my_msg = tkinter.StringVar() my_msg.set("在这里输入您的消息") entry_field = ttk.Entry(send_frame, textvariable=my_msg) entry_field.bind("<Return>", send) entry_field.pack(side="left", fill="x", expand=True) send_button = ttk.Button(send_frame, text="发送", command=send) send_button.pack(side="right") send_file_button = ttk.Button(send_frame, text="选择文件", command=choose_file) send_file_button.pack(side="left") send_image_button = ttk.Button(send_frame, text="选择图片", command=choose_image) send_image_button.pack(side="left") def init_chat_frame(): """ 创建聊天室区域 """ chat_frame = ttk.Frame(root) chat_frame.pack(fill="both", expand=True) global chat_box chat_box = tkinter.scrolledtext.ScrolledText(chat_frame) chat_box.pack(side="left", fill="both", expand=True) def start_chat(): """ 启动聊天室 """ # 获取昵称 global nickname nickname = simpledialog.askstring("昵称", "请输入您的聊天室昵称:", parent=root) # 连接到服务器 host = "localhost" # 端口号需与服务器端开启端口号相同 port = 9999 s.connect((host, port)) add_to_chat(f"您已成功连接到聊天室: {host}:{port}") s.send(nickname.encode("utf-8")) thread = threading.Thread(target=receive) thread.start() root = tkinter.Tk() root.title("聊天室") root.geometry("600x400") init_chat_frame() init_send_frame() start_chat() root.mainloop()

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值