Python编写多线程多人聊天室系统(Socket编程、tkinter组件使用)

是Python作业的说,也是自己编写了好长时间,有几个地方实现的方法非常的傻,请见谅QwQ

代码包含详细注释。

与此同时如果想让这个聊天室也能被全国各地的同学使用的话也可以将这个程序部署到云服务器上!在这里我也做了超级超级超级详细的教程,是有关阿里云的免费服务器的领取与使用,案例就是本文的案例哦!!可以参考下面连接,里面使用到的代码和这里的代码稍有不同~

超详细图文教程·阿里云免费学生ECS云服务器领取并使用全过程(部署Python多人聊天室程序)

运行结果与功能展示:

登录窗口展示 

 聊天窗口展示

 

多窗口登录使用展示

 昵称查重展示

 

 成员离开展示、自动定位聊天信息窗口结尾展示

 

运行记录展示


代码实现: 

服务器端:

from socket import *
from sqlite3 import connect
import threading
from datetime import *

# 时间格式声明,用于后面的记录系统时间
ISOTIMEFORMAT = '%Y-%m-%d %H:%M:%S'                     

# 设置IP地址和端口号
IP = '127.1.1.1'                 
PORT = 30000

# 用户列表和套接字列表,用于后面给每个套接字发送信息
user_list = []
socket_list = []

# 聊天记录存储至当前目录下的serverlog.txt文件中
try:
    with open('serverlog.txt', 'a+') as serverlog:                    
        curtime = datetime.now().strftime(ISOTIMEFORMAT)
        serverlog.write('\n\n-----------服务器打开时间:'+str(curtime)+',开始记录聊天-----------\n')
except:
    print('ERROR!')


# 读取套接字连接
s = socket()
s.bind((IP, PORT))
s.listen()
def read_client(s, nickname):                           
    try:
        return s.recv(2048).decode('utf-8')                     # 获取此套接字(用户)发送的消息
    except:                                                     # 一旦断开连接则记录log以及向其他套接字发送相关信息
        curtime = datetime.now().strftime(ISOTIMEFORMAT)        # 获取当前时间
        print(curtime)
        print(nickname + ' 离开了聊天室!')
        with open('serverlog.txt', 'a+') as serverlog:          # log记录
            serverlog.write(str(curtime) + '  ' + nickname + ' 离开了聊天室!\n')
        socket_list.remove(s)
        user_list.remove(nickname)
        for client in socket_list:                              # 其他套接字通知(即通知其他聊天窗口)
            client.send(('系统消息:'+ nickname + ' 离开了聊天室!').encode('utf-8'))



# 接收Client端消息并发送
def socket_target(s, nickname):                         
    try:
        s.send((','.join(user_list)).encode('utf-8'))               # 将用户列表送给各个套接字,用逗号隔开
        while True:
            content = read_client(s, nickname)                      # 获取用户发送的消息
            if content is None:
                break
            else:
                curtime = datetime.now().strftime(ISOTIMEFORMAT)    # 系统时间打印
                print(curtime)
                print(nickname+'说:'+content)
                with open('serverlog.txt', 'a+') as serverlog:      # log记录
                    serverlog.write(str(curtime) + '  ' + nickname + '说:' + content + '\n')
                for client in socket_list:                          # 其他套接字通知
                    client.send((nickname + '说:'+ content).encode('utf-8'))
    except:
        print('Error!')

while True:                                                     # 不断接受新的套接字进来,实现“多人”
    conn, addr = s.accept()                                     # 获取套接字与此套接字的地址
    socket_list.append(conn)                                    # 套接字列表更新
    nickname = conn.recv(2048).decode('utf-8')                  # 接受昵称

    if nickname in user_list:                                   # 昵称查重,相同则在后面加上数字
        i = 1
        while True:
            if nickname+str(i) in user_list:
                i = i + 1
            else:
                nickname = nickname + str(i)
                break

    user_list.append(nickname)                                  # 用户列表更新,加入新用户(新的套接字)
    curtime = datetime.now().strftime(ISOTIMEFORMAT)
    print(curtime)
    print(nickname + ' 进入了聊天室!')

    with open('serverlog.txt', 'a+') as serverlog:              # log记录
        serverlog.write(str(curtime) + '  ' + nickname + ' 进入了聊天室!\n')

    for client in socket_list[0:len(socket_list)-1]:            # 其他套接字通知
        client.send(('系统消息:'+ nickname + ' 进入了聊天室!').encode('utf-8'))

    # 加入线程中跑,加入函数为socket_target,参数为conn,nickname
    threading.Thread(target=socket_target, args=(conn,nickname,)).start()

客户端:

from tkinter import *
from datetime import *
from socket import *
import threading
import tkinter
import tkinter.messagebox
from tkinter.scrolledtext import ScrolledText

ISOTIMEFORMAT = '%Y-%m-%d %H:%M:%S'         # 时间格式声明
s = socket()                                # 套接字


# 登录窗口
def Login_gui_run():                                            

    root = Tk()
    root.title("小刘聊天系统·登录")          # 窗口标题
    frm = Frame(root)

    root.geometry('300x150')                # 窗口大小

    nickname = StringVar()                                      # 昵称变量

    def login_in():                                             # 登录函数(检查用户名是否为空,以及长度)
        name = nickname.get()                                   # 长度是考虑用户列表那边能否完整显示
        if not name:
            tkinter.messagebox.showwarning('Warning', message='用户名为空!')
        elif len(name)>10:
            tkinter.messagebox.showwarning('Warning', message='用户名过长!最多为十个字符!')
        else:
            root.destroy()
            s.connect(('127.1.1.1', 30000))                     # 建立连接
            s.send(nickname.get().encode('utf-8'))              # 传递用户昵称
            Chat_gui_run()                                      # 打开聊天窗口


    # 登录按钮、输入提示标签、输入框
    Button(root, text = "登录", command = login_in, width = 8, height = 1).place(x=100, y=90, width=100, height=35)
    Label(root, text='请输入昵称', font=('Fangsong',12)).place(x=10, y=20, height=50, width=80)
    Entry(root, textvariable = nickname, font=('Fangsong', 11)).place(x=100, y=30, height=30, width=180)

    root.mainloop()


# 聊天窗口
def Chat_gui_run():                                         
    window = Tk()
    window.maxsize(650, 400)                                # 设置相同的最大最小尺寸,将窗口大小固定
    window.minsize(650, 400)

    var1 = StringVar()
    user_list = []
    user_list = s.recv(2048).decode('utf-8').split(',')     # 从服务器端获取当前用户列表
    user_list.insert(0, '------当前用户列表------')


    nickname = user_list[len(user_list)-1]                  # 获取正式昵称,经过了服务器端的查重修改
    window.title("小刘聊天系统--"+nickname)                  # 设置窗口标题,体现用户专属窗口(不是)
    var1.set(user_list)                                     # 用户列表文本设置
    # var1.set([1,2,3,5])
    listbox1 = Listbox(window, listvariable=var1)           # 用户列表,使用Listbox组件
    listbox1.place(x=510, y=0, width=140, height=300)


    listbox = ScrolledText(window)                          # 聊天信息窗口,使用ScrolledText组件制作
    listbox.place(x=5, y=0, width=500, height=300)


    # 接收服务器发来的消息并显示到聊天信息窗口上,与此同时监控用户列表更新
    def read_server(s):
        while True:
            content = s.recv(2048).decode('utf-8')                      # 接收服务器端发来的消息
            curtime = datetime.now().strftime(ISOTIMEFORMAT)            # 获取当前系统时间
            listbox.insert(tkinter.END, curtime)                        # 聊天信息窗口显示(打印)
            listbox.insert(tkinter.END, '\n'+content+'\n\n')
            listbox.see(tkinter.END)                                    # ScrolledText组件方法,自动定位到结尾,否则只有消息在涨,窗口拖动条不动
            listbox.update()                                            # 更新聊天信息窗口,显示新的信息


            # 贼傻贼原始的用户列表更新方式,判断新的信息是否为系统消息,暂时没有想到更好的解决方案
            if content[0:5]=='系统消息:':
                if content[content.find(' ')+1 : content.find(' ')+3]=='进入':
                    user_list.append(content[5:content.find(' ')])
                    var1.set(user_list)
                if content[content.find(' ')+1 : content.find(' ')+3]=='离开':
                    user_list.remove(content[5:content.find(' ')])
                    var1.set(user_list)

    threading.Thread(target = read_server, args = (s,)).start()


    var2 = StringVar()                                      # 聊天输入口
    var2.set('')                                    
    entryInput = Entry(window, width = 140, textvariable=var2)
    entryInput.place(x=5, y=305, width = 600, height = 95)


    # 发送按钮触发的函数,即发送信息
    def sendtext():
        line = var2.get()
        s.send(line.encode('utf-8'))
        var2.set('')                                        # 发送完毕清空聊天输入口

    #发送按钮
    sendButton = Button(window, text = '发 送', font=('Fangsong', 18), bg = 'white', command=sendtext)     
    sendButton.place(x=500, y=305, width = 150, height = 95)

    window.mainloop()

Login_gui_run()
  • 36
    点赞
  • 274
    收藏
    觉得还不错? 一键收藏
  • 25
    评论
### 回答1: 实现一个 Python 多人聊天室可以分为以下步骤: 1. 创建一个服务器,监听客户端连接请求。 2. 当客户端连接到服务器时,服务器将客户端的连接请求接受,并记录客户端的套接字。 3. 服务器将客户端的消息转发给所有其他客户端,实现多人聊天的功能。 4. 如果某个客户端断开连接,服务器应该将该客户端的套接字从客户端列表中删除,并通知其他客户端。 以下是一个简单的 Python 多人聊天室的代码示例: ```python import socket import threading # 创建服务器套接字 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 绑定服务器套接字 server_socket.bind(('0.0.0.0', 9999)) # 监听客户端连接请求 server_socket.listen() # 客户端列表 clients = [] def handle_client(client_socket, addr): while True: try: # 接收客户端消息 msg = client_socket.recv(1024).decode() if not msg: break # 转发消息给其他客户端 for c in clients: if c != client_socket: c.send(f'{addr}: {msg}'.encode()) except: break # 关闭客户端连接 client_socket.close() clients.remove(client_socket) print(f'{addr} disconnected') while True: # 接受客户端连接 client_socket, addr = server_socket.accept() # 添加客户端到列表 clients.append(client_socket) # 启动客户端线程 client_thread = threading.Thread(target=handle_client, args=(client_socket, addr)) client_thread.start() # 输出客户端连接信息 print(f'{addr} connected') ``` 在这个例子中,我们使用Python 的 socket 模块来创建服务器套接字和客户端套接字,使用 threading 模块来实现多线程处理客户端连接。当客户端连接到服务器时,我们将客户端的套接字添加到客户端列表中,并启动一个新的线程来处理客户端的消息。当客户端发送消息时,服务器将消息转发给所有其他客户端。如果客户端断开连接,服务器将关闭客户端套接字,并从客户端列表中删除该套接字。 ### 回答2: Python多人聊天室是一个基于Python语言开发的应用程序,可以支持多个用户同时进行实时聊天和互动。 在实现Python多人聊天室的过程中,可以使用Socket编程来建立客户端与服务器之间的连接。通过创建一个服务器端和多个客户端,在服务器端建立一个监听套接字,接收客户端的连接请求,并为每个连接创建一个线程或进程来处理客户端的请求。 服务器端可以使用Python的socket模块来进行创建和管理套接字。服务器端需要监听某个IP地址和端口,接受来自客户端的连接请求。一旦建立连接,服务器端就可以接收到客户端发送的消息,并将其广播给其他客户端。 客户端可以使用Python的socket模块来创建套接字并连接到服务器。客户端可以通过输入消息并发送给服务器端,同时接收其他客户端发送过来的消息并显示在界面上。 为了实现多人聊天功能,可以使用线程或进程来处理多个客户端的连接和消息传递。每个客户端连接到服务器后,服务器端需要为该客户端创建一个线程或进程,用于接收该客户端的消息并将其广播给其他客户端。 在实现过程中,还可以使用其他第三方库来增强多人聊天室的功能和用户体验,例如使用Tkinter模块来构建GUI界面,使用pickle模块来对消息进行序列化和反序列化。 总的来说,Python多人聊天室可以通过Socket编程来实现客户端与服务器之间的连接和消息传递,通过线程或进程来处理多个客户端的连接和消息传输。这样就能够实现多个用户同时进行实时聊天和互动的功能。 ### 回答3: Python多人聊天室是一个支持多用户同时在线聊天程序。它使用Python编程语言编写,可以在多个终端上同时运行。 这个聊天室的实现主要依赖于Python的socket库和多线程编程。它通过创建一个服务器端和多个客户端来实现用户之间的实时通信。 在服务器端,我们首先创建一个socket对象,并通过bind()函数将其绑定到一个特定的IP地址和端口号上。然后,通过listen()函数开始监听客户端的连接请求。 一旦有客户端尝试连接,我们通过accept()函数接受连接请求,并在新创建的线程中为该客户端提供服务。每个客户端连接都会创建一个新的线程,这样可以确保服务器可以同时处理多个客户端的请求。 在客户端,我们也先创建一个socket对象,并通过connect()函数连接到服务器端的IP地址和端口号上。然后,通过不断地接收和发送消息,实现与其他用户的实时聊天。 为了实现多人聊天功能,我们可以使用一些数据结构来保存在线用户的信息,比如使用一个字典来保存每个用户的用户名和对应的socket对象。 在服务器端,我们可以通过广播的方式将一条消息发送给所有的在线用户。通过使用线程锁来保证多个线程同时对这个字典进行读写的安全性。 综上所述,Python多人聊天室可以为多个用户提供实时的聊天功能。它使用Python的socket库和多线程编程来实现用户间的通信,并通过广播方式将消息发送给所有在线用户。通过合理地使用数据结构和线程锁,我们可以确保多人聊天室的安全和稳定性。
评论 25
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值