Python多人聊天室

这篇具有很好参考价值的文章主要介绍了Python多人聊天室。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

多人聊天室的实现

一. 源代码链接

链接:https://pan.baidu.com/s/1kzxiLTkvdxGAMgF3SQzcaw?pwd=vb9h
提取码:vb9h

二. 项目简介

  1. 利用socket方式编写一个多人聊天室程序,可以实现多个用户之间的群聊功能,私聊功能,显示当前用户功能
  2. 在聊天室程序中增加利用ftp实现文件的上传,下载,删除,查看当前文件功能
  3. 在聊天室程序中增加利用ftp实现在聊天过程中可以发送图片功能
  4. 在聊天室程序中增加发送邮件功能,并提供附件发送服务

三. 功能演示

  1. 设置好服务端的配置代码
    python+socket实现多人聊天室,Python,python,服务器,网络

  2. 登录界面
    python+socket实现多人聊天室,Python,python,服务器,网络

  3. 使用过程
    python+socket实现多人聊天室,Python,python,服务器,网络

四. 模块化分析

1. 服务端

服务端主要用于为客户端提供聊天服务和FTP服务,所以我分别创建了两个类为ChatServer和FtpServer

①对于服务端的代码分析,首先是要让用户对服务器的基本信息进行设置,具体设置代码如下
# 用户所需输入信息分界线--------------------------------------
IP_server = '127.0.0.1'
PORT = 6666
FTP_PORT = 21

# 关于ftp的设置
username_server = 'mary'  # ftp登录用的用户名
password_server = '123456'
ftp_catalogue = 'C:/my_soft/python/code/lesson_code/ftp_test'  # ftp的目录
user_power = 'elradfmwMT'  # 权限
# 用户所需输入信息分界线--------------------------------------
②对于聊天服务器,主要模块可以分为

(1)TCP连接模块,主要代码就是与客户端建立起TCP通信
(2)当前在线用户模块,主要就对当前连接的客户端数目进行判断,然后返回一个当前在线用户数
(3)接收信息模块,主要代码是接收客户端发来的信息,然后存入一个队列中
(4)发送信息模块,主要代码是对客户端发来的信息进行分析,分析完后转入对于的函数去执行相关操作,比如接收到的是聊天信息就发到聊天用户的客户端中,接收到的是图片信息就发送指定字符串给聊天用户的客户端,然后对指定图片执行FTP上传下载操作。
(5)服务器启动检查模块,主要是令服务端与客户端进行连接,然后在控制台内打印连接状况的信息。

③对于FTP服务器,主要代码是用于初始化FTP服务器,如设置FTP的用户,密码和FTP的文件夹,具体如下图所示
# ----------------------------------------文件传输服务器1--------------------------
class FtpServer():
    # 新建一个用户组
    authorizer = DummyAuthorizer()
    # 将用户名,密码,指定目录,权限 添加到里面
    authorizer.add_user(username_server, password_server, ftp_catalogue, perm=user_power)  # adfmw
    # 这个是添加匿名用户,任何人都可以访问,如果去掉的话,需要输入用户名和密码,可以自己尝试
    authorizer.add_anonymous(ftp_catalogue)

    handler = FTPHandler
    handler.authorizer = authorizer

    def run(self):
        # 开启服务器
        server = FTPServer((IP_server, FTP_PORT), self.handler)
        server.serve_forever()
# ----------------------------------------文件传输服务器2--------------------------

2. 客户端

①初始登录模块,即用tkinter库创建出一个界面,再在里面添加输入框,最后将用户输入的信息保存为对应的全局变量给后续代码使用。核心代码如下所示
# 登录按钮
def login(*args):
    global IP, PORT, user, ftpUser, ftpPassword
    IP, PORT = entryIP.get().split(':')  # 获取IP和端口号
    PORT = int(PORT)  # 端口号需要为int类型
    user = entryUser.get()
    ftpUser = entryFtpUser.get()
    ftpPassword = entryFtpPassword.get()
    if not user:
        tkinter.messagebox.showerror('错误', message='请输入用户名')
    else:
        root1.destroy()  # 关闭登录窗口
②聊天窗口模块,即登录成功后为用户显示出来的窗口,用于用户聊天和进行其他操作,主要也是利用了tkinter库来创建出对应的界面
③图片发送模块,具体思路如下

(1)先进行FTP登录,方便后续把图片发送到服务器中
(2)打开本地文件资源管理器,找到图片的位置,修改图片的大小,因为聊天窗口无法加载过大的图片
(3)利用FTP把图片上传到服务器中
(4)给服务器发送一个指定的消息,表示这是一个发送图片命令

④显示当前在线用户模块,主要原理是先接收服务端发来的当前在线用户数,然后插入到聊天窗口中即可。
⑤与服务器通信模块,主要思路是先根据窗口信息确定聊天对象,然后再根据用户输入信息确定聊天内容,最后将这些信息加上分隔符后拼接成字符串,然后发送给服务端。核心代码如下
def send(*args):
    # 没有添加的话发送信息时会提示没有聊天对象
    users.append('------群聊模式-------')
    print(chat)
    if chat not in users:
        tkinter.messagebox.showerror('Send error', message='There is nobody to talk to!')
        return
    if chat == user:
        tkinter.messagebox.showerror('Send error', message='Cannot talk with yourself in private!')
        return
    mes = entry.get() + ':;' + user + ':;' + chat  # 添加聊天对象标记
    s.send(mes.encode())
    a.set('')  # 发送后清空文本框
⑥私聊模块,主要思路是确定好聊天的两个对象,然后将用户和其聊天对象名拼接成字符串显示到聊天框中,方便用户确定当前聊天对象,核心代码如下
def private(*args):
    global chat
    # 获取点击的索引然后得到内容(用户名)
    indexs = listbox1.curselection()
    index = indexs[0]
    if index > 0:
        chat = listbox1.get(index)
        # 修改客户端名称
        if chat == '------群聊模式-------':
            root.title(user + ' 的群聊窗口')
            return
        # 下面这两行用于在标题头处显示目前是谁和谁在聊天
        ti = user + '  与  ' + chat + ' 的聊天窗口'
        root.title(ti)
⑦邮件功能模块,主要思路如下

(1)在聊天窗口上扩大面积,插入输入框让用户填写发送邮件所需的对应信息、
(2)收集用户输入的信息,用对应的变量来保存
(3)对邮件的附件类型进行判断,以合适方式保存好插入邮件中
(4)登录邮箱服务器,发送邮件,核心代码如下

def send_mail():
        global fileName_mail_img
        global fileName_mail_file
        global fileName_mail_text
        global fileName_mail_video
        # 然后给对应变量赋值即可
        sender = entry_sender.get()
        # sender = input('请输入一个电子邮箱地址(163/QQ):')
        username, domain = sender.split('@')
        if domain == '163.com':
            host = 'smtp.163.com'
        elif domain == 'qq.com':
            host = 'smtp.qq.com'
        else:
            # print('当前代码只识别163和QQ邮箱,请检查邮箱地址或修改代码。')
            exit()
        port = 25

        body = entry_mail_body.get("1.0", "end")  # 这个get里面的参数是获得所有信息的

        # 输入密码,无回显,需要在cmd或PowerShell运行程序
        userpwd = entry_sender_passwd.get()
        # 要群发的电子邮件地址
        recipients = entry_recipients.get()

        # 登录邮箱服务器
        with SMTP(host, port) as server:
            server.starttls()
            server.login(username, userpwd)

            # 创建邮件
            msg = MIMEMultipart()
            msg.set_charset('utf-8')
            # 回复地址与发信地址可以不同
            # 但是大部分邮件系统在回复时会提示
            msg['Reply-to'] = sender
            # 设置发信人、收信人和主题
            msg.add_header('From', sender)
            msg.add_header('To', recipients)
            msg.add_header('Subject', entry_mail_topic.get())
            msg['Date'] = formatdate()
            msg['Message-Id'] = make_msgid()
            # 设置邮件文字内容
            msg.attach(MIMEText(body, 'plain', _charset='utf-8'))

            # ---------------------------------这里为添加附件功能-------------------
            # 首先是要打开一个窗口,然后获取到对应的文件名
            # 添加图片
            fn = fileName_mail_img
            print(fn)
            if fn :
                with open(fn, 'rb') as fp:
                    attachment = MIMEImage(fp.read())
                    attachment.add_header('content-disposition',
                                          'attachment', filename=fn.split('/')[-1])
                    msg.attach(attachment)

            # 添加文本文件
            fn = fileName_mail_text
            print(fn)
            if fn:
                with open(fn, 'rb') as fp:
                    attachment = MIMEBase('text', 'txt')
                    attachment.set_payload(fp.read())
                    encode_base64(attachment)
                    attachment.add_header('content-disposition',
                                          'attachment',
                                          filename=fn.split('/')[-1])
                    msg.attach(attachment)

            # 添加可执行程序
            fn = fileName_mail_file
            print(fn)
            if fn:
                with open(fn, 'rb') as fp:
                    attachment = MIMEApplication(fp.read(),
                                                 _encoder=encode_base64)
                    attachment.add_header('content-disposition',
                                          'attachment', filename=fn.split('/')[-1])
                    msg.attach(attachment)

            # 添加音乐文件
            fn = fileName_mail_video
            print(fn)
            if fn:
                with open(fn, 'rb') as fp:
                    attachment = MIMEAudio(fp.read(), 'plain',
                                           _encoder=encode_base64)
                    attachment.add_header('content-disposition',
                                          'attachment', filename=fn.split('/')[-1])
                    msg.attach(attachment)
            # 发送邮件
            server.send_message(msg)

            # 每次发完清空附件
            fileName_mail_file = ''
            fileName_mail_text = ''
            fileName_mail_video = ''
            fileName_mail_img = ''
⑧FTP功能模块,主要思路如下

(1)增大聊天窗口的界面,为用户提供进行FTP操作的按钮
(2)根据之前用户输入的信息进行FTP登录
(3)利用ftp.dir函数获取FTP服务器内的文件名称,将其存入数组中,然后提供翻页按钮,每次取出14条文件名称展示到聊天窗口中,核心代码为

def show_ftp():
        global now_page
        # 将打印出来的数据截取出对应的文件名(这个有点巧妙)
        dir_res = []
        ftp.dir('.', dir_res.append)  # 对当前目录进行dir(),将结果放入列表
        # print(dir_res)
        print(len(dir_res))     # 打印列表长度
        # 由文件名判断名称是文件还是目录
        for i in range(14):
            # 防止数组越界
            if (now_page*14)+i <= len(dir_res)-1:
                name = dir_res[(now_page*14)+i].split(' ')[-1]
                # print(name)
                # 将名称插入列表
                list2.insert(tkinter.END, name)
                # 通过.号判断是否为文件或文件夹,从而赋予不同的颜色(暂时未测试过文件夹)
                if '.' not in name:
                    list2.itemconfig(tkinter.END, fg='orange')
                else:
                    list2.itemconfig(tkinter.END, fg='blue')

(4)提供文件上传或文件夹上传服务,如果是文件就直接调用FTP的函数上传,如果是文件夹就先切换到该文件夹中,再遍历其中的文件并依次上传到FTP服务器中。上传文件夹的核心代码如下

def upload_ftpdir():
        # 思路:先获取到对应文件名,然后以二进制形式上传,ftp的目录信息是在服务端进行设置的
        # 获取文件夹名,并判断ftp目录里是否存在该文件夹
        fileName_ftp = tkinter.filedialog.askdirectory()
        fileName_ftp_end = fileName_ftp.split('/')[-1]
        dir = []
        ftp.dir('.', dir.append)  # 对当前目录进行dir(),将结果放入列表
        # 将打印信息拼接成字符串,方便后面的not in 判断
        rubbish = ''
        for i in dir:
            rubbish = rubbish + i
            # print(rubbish)
        if fileName_ftp_end not in rubbish:
            # 不存在则创建文件夹
            ftp.mkd(fileName_ftp_end)
            # 然后进行下载
            ftp.cwd(fileName_ftp_end)
            dir_res = []
            files = os.listdir(fileName_ftp)
            print(files)
            for i in files:
                dir_res.append(i)
            print(dir_res)
            for name in dir_res:
                print(fileName_ftp + '/' + name)
                fd = open(fileName_ftp + '/' + name, 'rb')
                # 以二进制的形式上传
                ftp.storbinary("STOR %s" % name, fd)
                fd.close()
        else:
            ftp.cwd(fileName_ftp_end)
            dir_res = []
            files = os.listdir(fileName_ftp)
            print(files)
            for i in files:
                dir_res.append(i)
            print(dir_res)
            # ftp.dir(fileName_ftp_end, dir_res.append)  # 对当前目录进行dir(),将结果放入列表
            # print(dir_res)
            for name in dir_res:
                print(fileName_ftp + '/' + name)
                fd = open(fileName_ftp + '/' + name, 'rb')
                # 以二进制的形式上传
                ftp.storbinary("STOR %s" % name, fd)
                fd.close()
        # 传完文件后再把目录切回原目录,再刷新界面
        ftp.cwd('..')
        # 上传完文件后刷新一遍目录窗口,首先要清空目录,再重载
        list2.delete(0, tkinter.END)  # 清空列表框
        show_ftp()
        print("upload finished")

(5)提供下载文件服务,主要思路是先获取用户在聊天窗口中选中的文件名称,然后用这个文件名称去FTP服务器进行查找,最后将其下载到指定文件夹中,如果用户选择下载的是文件夹,那就先切换到文件夹中,再依次遍历其中的文件并下载到指定目录中。核心代码如下

def download_ftp():
        # 获取到要下载到本地的文件名(只需要名字就行)
        fileName_ftp = list2.get(list2.curselection())
        print(fileName_ftp)
        # 对文件名做判断
        if '.' not in fileName_ftp:
            # 如果是文件夹的话就切换ftp目录进该文件夹,再下载,最后返回源目录
            ftp.cwd(fileName_ftp)
            dir_res = []
            # 将目录内文件信息保存到dir_res中
            ftp.dir('.', dir_res.append)  # 对当前目录进行dir(),将结果放入列表
            # print(dir_res)
            # 从dir_res中取出文件名放入files数组中
            files = []
            for i in dir_res:
                files.append(i.split(' ')[-1])
            # print(files)
            # 设置文件存储路径(路径为文件夹类型)
            dir_path = tkinter.filedialog.askdirectory()
            os.mkdir(dir_path + '\\' + fileName_ftp)
            # print(dir_path_end)
            for j in files:
                # 是文件的话就直接下载
                # 这里要对目录路径进行一些小替换以符合格式
                dir_path_end = dir_path.replace("/", '\\') + '\\' + fileName_ftp + '\\' + j
                fd = open(dir_path_end, 'wb')
                # 以二进制形式下载,注意第二个参数是fd.write,上传时是fd
                ftp.retrbinary("RETR %s" % j, fd.write)
                fd.close()
            ftp.cwd('..')
        else:
            # 是文件的话就直接下载
            # 设置文件存储路径(路径为文件夹类型)
            dir_path = tkinter.filedialog.askdirectory()
            # 这里要对目录路径进行一些小替换以符合格式
            dir_path_end = dir_path.replace("/", '\\') + '\\' + fileName_ftp
            print(dir_path_end)
            fd = open(dir_path_end, 'wb')
            # 以二进制形式下载,注意第二个参数是fd.write,上传时是fd
            ftp.retrbinary("RETR %s" % fileName_ftp, fd.write)
            fd.close()
        print("download finished")

(6)提供删除FTP服务器内文件服务。主要思路是先获取用户在聊天窗口中选中的文件名称,然后判断文件是单个文件还是文件夹,最后调用相应的FTP函数进行删除。核心代码如下

def delete_ftp():
        # 获取到要下载到本地的文件名(只需要名字就行)
        fileName_ftp = list2.get(list2.curselection())
        print(fileName_ftp)
        # 通过.号判断是否为文件或文件夹,从而赋予不同的颜色
        if '.' not in fileName_ftp:
            # 因为rmd命令只能删空目录
            # 所以我们要先递归删除目录里的文件
            dir_res = []
            ftp.dir(fileName_ftp, dir_res.append)  # 对当前目录进行dir(),将结果放入列表
            print(dir_res)
            for i in dir_res:
                name = i.split(' ')[-1]
                print(name)
                ftp.delete(fileName_ftp + '/' + name)
            ftp.rmd(fileName_ftp)
        else:
            ftp.delete(fileName_ftp)
        print("delete finished")
        # 上传完文件后刷新一遍目录窗口,首先要清空目录,再重载
        list2.delete(0, tkinter.END)  # 清空列表框
        show_ftp()
⑨接收服务端发来的信息模块,主要思路是

(1)首先判断接收到的信息是否抛出异常,如果没有捕获到异常则接收到的是当前在线用户列表,则取出其中的当前在线用户名并依次插入到聊天窗口中。
(2)然后判断接收到的信息的指定位置是否含有特殊词“image”,如果有的话代表是发送图片的命令,则连接上FTP服务器并根据图片名称下载到本地,然后在本地打开该图片并加载到聊天窗口中。
(3)如果以上判断均不成立,则为普通的聊天信息。然后判断聊天对象,最后把聊天内容发送给对应的聊天对象的客户端即可。文章来源地址https://www.toymoban.com/news/detail-769150.html

到了这里,关于Python多人聊天室的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于Python web的多人聊天室

              本文介绍了基于即时通讯的Python实现web版多人聊天室的设计和实现。这个系统利用了多种先进的技术,如Django、Channels、WebSocket,来实现即时通信,并利用MySQL和Redis作为数据库,同时还采用了多种前端技术,如bootstrap、CSS、html和js,来提供出色的用户体验。该系

    2024年02月16日
    浏览(27)
  • Python web实战 | 使用 Flask 实现 Web Socket 聊天室

        今天我们学习如何使用 Python 实现 Web Socket,并实现一个实时聊天室的功能。本文的技术栈包括 Python、Flask、Socket.IO 和 HTML/CSS/JavaScript。   Web Socket 是一种在单个 TCP 连接上进行全双工通信的协议。它是 HTML5 中的一部分,并且可以在浏览器和服务器之间创建实时的交互式

    2024年02月14日
    浏览(36)
  • python 使用socket制作聊天室-(附带 源码 可以直接运行)

    为什么socket能做聊天室呢 socket提供了通信的服务 比如你可以创建tcp udp的请求 向某个主机发起通信 就像是你想和某人说话 你得会发音 就是提供了服务端的方式和客户端的方式 服务端处理用户发起的请求 客户端发送数据和接收服务端的响应数据 就像你打开浏览器看视频 你

    2024年02月08日
    浏览(31)
  • [Socket]Python用UDP协议建立带有私聊功能的网络聊天室-建立聊天工具

    前些天实习面试的时候被面试官问到Socket编程的问题,即“Socket创建和释放的具体过程是什么”,当时答不上来,似乎是涉及到发送和接收缓冲区的问题。由于自己在Socket编程这一块知识较为薄弱,于是写下这篇文章,当作复习下Socket编程知识。 首先,该实验是我在大三上学

    2024年02月03日
    浏览(34)
  • 【Linux网络编程】基于UDP实现多人聊天室

    UDP(User Datagram Protocol)用户数据报协议,是不可靠的无连接的协议。在数据发送前,因为不需要进行连接,所以可以进行高效率的数据传输。 数据报格式套接字 SOCK_DGRAM 采用UDP只管发送数据而不去验证发送数据的正确性,不论传输是否被接收,数据流是否有丢失,都不再重新发

    2024年02月08日
    浏览(41)
  • C语言实现--基于UDP的多人在线聊天室

    目录 实现功能 实现思想 实现代码(部分及详解) 服务端部分代码 客户端部分代码 实现效果 项目中出现的问题和解决方法 项目整体代码展示 代码优化思路 服务端代码 客户端代码 服务端可以同时连接多个客户端; 新的客户端连接服务端时,可以在服务端显示自己的名字并

    2024年02月04日
    浏览(44)
  • WebSocket+Vue实现简易多人聊天室 以及 对异步调用的理解

    代码仓库:github   HTTP是不支持长连接的,WebSocket是一种通信协议,提供了在单一、长连接上进行全双工通信的方式。它被设计用于在Web浏览器和Web服务器之间实现,但也可以用于任何需要实时通信的应用程序。使用ws作为协议标识符,如果需要加密则使用wss作为协议标识符

    2024年01月17日
    浏览(44)
  • Java 多人聊天室

    Java实训做的多人聊天室,效果如图: 能够实现多个客户端之间的互相聊天,服务端来负责接收数据和转发数据。 每个客户端可以自己设置和修改自己的名称,并传给服务器让其他客户端知道。 当有客户端加入和退出时,群聊里每个客户端都有提示。(优化了异常检测,意外

    2024年02月10日
    浏览(25)
  • .NET编程——利用C#实现基于Socket类的聊天室(WinForm)

    在学习C#和MySQL实现注册登录和TCP协议的Socket通信后,本文将介绍如何利用Socket类中的异步通信函数来实现本地聊天室功能, Socket通信限制了客户端与客户端之间的通信,客户端只能接收来自服务器的消息而不能接收到客户端发送的消息,因此服务器最佳的选择是起到一个中

    2023年04月21日
    浏览(44)
  • vue3-多人聊天室角色识别(全栈)

    主要技术栈是vue3,springboot,websocket,element-plus 主要目的是复习和梳理 发送信息,包装信息,转json,用socket发送到后端,使输入栏清空 后端解析json,因为是socket接口,所以不能用@requestbody解析json,用以下方式解析json 设置发送时间为当前时间,然后执行mapper数据库插入 广

    2024年02月11日
    浏览(25)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包