Python多人聊天室-基于socket UDP协议

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

简介

使用Python编写的基于socket UDP通信的多功能即时聊天室,包含Tkinter编写的图形化聊天界面,功能包括有账号注册和登录,登录成功后可以查看在线用户,并和聊天室内的其他在线用户聊天,包含私聊和群发,能发送文字、表情包,以及文件等。

功能

  • 登录和注册
  • 显示在线用户
  • 群聊和私聊
  • 发送文字消息和表情包
  • 发送文件
  • 其他功能可自行添加

界面演示

(1)登录界面

Python多人聊天室-基于socket UDP协议

(2)注册界面

Python多人聊天室-基于socket UDP协议

(3)聊天界面

Python多人聊天室-基于socket UDP协议

部分源代码

(1)登录界面源代码

import random
import sqlite3
from tkinter import *
from tkinter import messagebox
from PIL import Image, ImageTk
from need_module import json,ctypes,sys,os



class Login(object):
    def __init__(self, Register,Chat,master=None):
        self.root = master  # 定义内部变量root
        self.root.title('登录窗口')
        self.Register=Register
        self.Chat=Chat
        self.root.iconbitmap(r'images/icon/login.ico')  # 设置左上角窗口图标


        # 设置窗口居中
        sw = self.root.winfo_screenwidth()  # 计算水平距离
        sh = self.root.winfo_screenheight()  # 计算垂直距离
        w = 690  # 宽
        h = 535  # 高
        x = (sw - w) / 2
        y = (sh - h) / 2
        self.root.geometry("%dx%d+%d+%d" % (w, h, (x + 160), y))
        self.root.resizable(0, 0)  # 窗口设置为不可放大缩小
        # 告诉操作系统使用程序自身的dpi适配
        ctypes.windll.shcore.SetProcessDpiAwareness(1)
        # 获取屏幕的缩放因子
        ScaleFactor = ctypes.windll.shcore.GetScaleFactorForDevice(0)
        # 设置程序缩放
        self.root.tk.call('tk', 'scaling', ScaleFactor / 75)
        self.creatlogin()

    def creatlogin(self):
        self.fr2 = Frame(self.root)
        self.fr2.pack()
        self.fr1 = Frame(self.root)
        self.fr1.pack(pady=10)

        self.benner_list = ['images/benner/banner-1.jpg', 'images/benner/banner-2.jpg', 'images/benner/banner-3.jpg',
                            'images/benner/banner-4.jpg', 'images/benner/banner-5.jpg', 'images/benner/banner-6.jpg', ]
        self.benner_img = random.choice(self.benner_list)  # 随机一张背景图

        # 图片大小:690x300
        self.pic = Image.open(self.benner_img)
        self.login_benner = ImageTk.PhotoImage(self.pic)

        # 标签 图片
        self.imgLabel = Label(self.fr2, image=self.login_benner)
        self.imgLabel.pack()

        # 标签 用户和密码
        self.label_usr = Label(self.fr1, text="用户名:")
        self.label_usr.grid(row=0, column=0, pady=10)
        self.label_pwd = Label(self.fr1, text="密  码:")
        self.label_pwd.grid(row=1, column=0)

        # 文本框 用户名
        self.var_usr_name = StringVar()
        self.entry_name = Entry(self.fr1, textvariable=self.var_usr_name)
        self.entry_name.grid(row=0, column=1)
        self.entry_name.focus_set()  # 获得焦点
        # 文本框 密码
        self.var_usr_pwd = StringVar()
        self.entry_pwd = Entry(self.fr1, textvariable=self.var_usr_pwd, show="*")
        self.entry_pwd.grid(row=1, column=1)

        self.saved_msg()

        self.fr3 = Frame(self.root)
        self.fr3.pack()
        self.rd_login = IntVar()
        self.rd_Passwd = IntVar()
        self.checkboxLogin = Checkbutton(self.fr3, text="自动登录", variable=self.rd_login)
        self.checkboxPasswd = Checkbutton(self.fr3, text="记住密码", variable=self.rd_Passwd)

        self.la = Label(self.fr3, width=5)
        self.la.grid(row=0, column=0)
        self.checkboxLogin.grid(row=0, column=1)
        self.checkboxPasswd.grid(row=0, column=2)
        # 登录
        self.root.bind('<Return>', self.check_login)  # 绑定回车键

        self.bt_login = Button(self.fr3, text=" 登录 ", command=lambda: self.check_login())
        self.bt_login.grid(row=1, column=1, pady=5)
        self.bt_quit = Button(self.fr3, text=" 退出 ", command=sys.exit)
        self.bt_quit.grid(row=1, column=2)

        # # 底部标签
        self.fr4 = Frame(self.root)
        self.fr4.pack(side='bottom')

        self.bt_register = Button(self.fr4, text=" 注册账号", relief=FLAT, bg='#f0f0f0', command=self.login_win_close)
        self.bt_register.pack(side='left', anchor='s')
        self.la2 = Label(self.fr4, width=150)
        self.la2.pack()
        self.tsLabel2 = Label(self.fr4, text="聊天登录界面 by LGH ", fg="red")
        self.tsLabel2.pack(side='right', anchor='s', pady=5)

    def red_msg(self):
        if self.rd_Passwd.get() == 1:
            # 创建新的JSON
            new_usr = {
                'username': self.var_usr_name.get(),
                'password': self.var_usr_pwd.get()
            }
            with open('usr.json', 'w') as wp:
                json.dump(new_usr, wp)

    def saved_msg(self):
        self.saved_name = ''
        self.saved_pwd = ''
        if os.path.exists('usr.json'):
            with open('usr.json', 'r') as fp:
                json_file = json.load(fp)
                json_str = json.dumps(json_file)

                json_date = json.loads(json_str)
                print(json_date)
                self.saved_name = json_date['username']
                self.saved_pwd = json_date['password']
                # print(self.saved_name,self.saved_pwd)
        if self.saved_name != '':
            self.entry_name.insert(END, self.saved_name)
            self.entry_pwd.insert(END, self.saved_pwd)

    def login_win_close(self):

        self.fr1.destroy()
        self.fr2.destroy()
        self.fr3.destroy()
        self.fr4.destroy()  # 登录界面卸载
        self.Register(Login,self.Chat,self.root)  # 密码对,就把主窗体模块的界面加载

    def check_login(self, *args):
        global usr_name
        self.usr_name = self.var_usr_name.get()
        self.usr_pwd = self.var_usr_pwd.get()
        conn = sqlite3.connect('yonghu.db')
        cursor = conn.cursor()

        if self.usr_name == '' or self.usr_pwd == '':
            messagebox.showwarning(title='提示', message="用户名密码不能为空")

        else:
            # 执行查询语句:
            cursor.execute('select username from user')
            values = cursor.fetchall()
            cursor.execute('select password from user where username="%s"' % self.usr_name)
            # 获得查询结果集:
            values2 = cursor.fetchall()
            userList = []
            for i in values:
                # print(i[0])
                userList.append(i[0])

            if self.usr_name in userList:
                if self.usr_pwd == values2[0][0]:
                    messagebox.showinfo(title='提示', message='登录成功,欢迎回来!')
                    self.root.unbind('<Return>')  # 解绑回车键事件
                    self.red_msg()
                    print('是否记住密码:',self.rd_Passwd.get())
                    self.fr1.destroy()
                    self.fr2.destroy()
                    self.fr3.destroy()
                    self.fr4.destroy()  # 登录界面卸载
                    self.Chat(self.usr_name)

                else:
                    messagebox.showerror(title='提示', message="用户名密码错误!")
            else:
                messagebox.showerror(title='提示', message="没有该用户名!")
            cursor.close()
            conn.close()
            # 下面返回字符串break使回车绑定事件只触发绑定的方法而不进行默认的换行操作
            return 'break'

(2)注册界面源代码

import random
import sqlite3
from tkinter import *
from tkinter import messagebox
from PIL import Image, ImageTk
from need_module import sys

class Register(object):
    def __init__(self, Login,Chat,master=None):
        self.root = master  # 定义内部变量root
        self.root.title('注册窗口')
        self.Login=Login
        self.Chat=Chat

        # 设置窗口居中
        sw = self.root.winfo_screenwidth()  # 计算水平距离
        sh = self.root.winfo_screenheight()  # 计算垂直距离
        w = 690  # 宽
        h = 520  # 高
        x = (sw - w) / 2
        y = (sh - h) / 2
        self.root.geometry("%dx%d+%d+%d" % (w, h, (x + 160), y))
        self.root.iconbitmap(r'images/icon/register.ico')  # 设置左上角窗口图标
        self.root.resizable(0, 0)  # 窗口设置为不可放大缩小
        # # 告诉操作系统使用程序自身的dpi适配
        # ctypes.windll.shcore.SetProcessDpiAwareness(1)
        # # 获取屏幕的缩放因子
        # ScaleFactor = ctypes.windll.shcore.GetScaleFactorForDevice(0)
        # # 设置程序缩放
        # self.root.tk.call('tk', 'scaling', ScaleFactor / 75)
        self.creatregister()

    def creatregister(self):
        self.fr2 = Frame(self.root)
        self.fr2.pack()
        self.fr1 = Frame(self.root)
        self.fr1.pack(pady=10)

        self.benner_list = ['images/benner/banner-1.jpg', 'images/benner/banner-2.jpg', 'images/benner/banner-3.jpg',
                            'images/benner/banner-4.jpg', 'images/benner/banner-5.jpg', 'images/benner/banner-6.jpg', ]
        self.benner_img = random.choice(self.benner_list)  # 随机一张背景图

        # 图片大小:690x300
        self.pic = Image.open(self.benner_img)
        self.register_benner = ImageTk.PhotoImage(self.pic)

        # 标签 图片
        self.imgLabel = Label(self.fr2, image=self.register_benner)
        self.imgLabel.pack()

        # 标签 用户和密码
        self.label_usr = Label(self.fr1, text="用户名:")
        self.label_usr.grid(row=0, column=0)
        self.label_pwd = Label(self.fr1, text="密  码:")
        self.label_pwd.grid(row=1, column=0, pady=5)
        self.label_repwd = Label(self.fr1, text="确认密码:")
        self.label_repwd.grid(row=2, column=0)

        # 文本框 用户名
        self.var_usr_name = StringVar()
        self.entry_name = Entry(self.fr1, textvariable=self.var_usr_name)
        self.entry_name.grid(row=0, column=1)
        self.entry_name.focus_set()  # 获得焦点
        self.docheck1 = self.entry_name.register(self.usercheck)  # 自带验证功能,usercheck自定义函数
        self.entry_name.config(validate='all', validatecommand=(self.docheck1, '%P'))

        # 文本框 密码
        self.var_usr_pwd = StringVar()
        self.entry_pwd = Entry(self.fr1, textvariable=self.var_usr_pwd, show="*")
        self.entry_pwd.grid(row=1, column=1)
        self.docheck2 = self.entry_pwd.register(self.passwordcheck)
        self.entry_pwd.config(validate='all', validatecommand=(self.docheck2, '%d', '%S'))
        # 文本框 确认密码
        self.var_usr_repwd = StringVar()
        self.entry_repwd = Entry(self.fr1, textvariable=self.var_usr_repwd, show="*")
        self.entry_repwd.grid(row=2, column=1)

        self.fr3 = Frame(self.root)
        self.fr3.pack()
        # 登录
        self.root.bind('<Return>', self.reg)  # 绑定回车键
        self.bt_register = Button(self.fr3, text=" 注册 ", command=lambda: self.reg())
        self.bt_register.grid(row=1, column=1, pady=5, padx=35)
        # self.la = Label(self.fr3, width=5)
        # self.la.grid(row=0, column=0)
        self.bt_quit = Button(self.fr3, text=" 退出 ", command=sys.exit)
        self.bt_quit.grid(row=1, column=2)

        # # 底部标签
        self.fr4 = Frame(self.root)
        self.fr4.pack(side='bottom')

        self.bt_register = Button(self.fr4, text=" 返回登录", relief=FLAT, bg='#f0f0f0', command=self.register_win_close)
        self.bt_register.pack(side='left', anchor='s')
        self.la2 = Label(self.fr4, width=150)
        self.la2.pack()
        self.tsLabel2 = Label(self.fr4, text="用户注册界面 by LGH ", fg="red")
        self.tsLabel2.pack(side='right', anchor='s', pady=5)

    def register_win_close(self):
        self.fr1.destroy()
        self.fr2.destroy()
        self.fr3.destroy()
        self.fr4.destroy()  # 登录界面卸载
        self.Login(Register,self.Chat,self.root)  # 密码对,就把主窗体模块的界面加载

    def usercheck(self, what):
        if len(what) > 8:
            self.la2.config(text='用户名不能超过8个字符', fg='red')
            return False
        return True

    def passwordcheck(self, why, what):
        if why == '1':
            if what not in '0123456789':
                self.la2.config(text='密码只能是数字', fg='red')
                return False
        return True

    def reg(self, *args):

        usr_name = self.var_usr_name.get()
        usr_pwd = self.var_usr_pwd.get()
        usr_repwd = self.var_usr_repwd.get()

        if usr_name == '' or usr_pwd == '' or usr_repwd == '':
            messagebox.showwarning(title='提示', message="用户名密码不能为空")

        else:
            # 如果文件不存在,会自动在当前目录创建:
            conn = sqlite3.connect('yonghu.db')
            # 创建一个Cursor:
            cursor = conn.cursor()
            # 执行一条SQL语句,创建user表:
            cursor.execute('create table if not exists user(username varchar(20),password varchar(20))')

            # 查询用户名是否存在
            cursor.execute('select username from user')
            values = cursor.fetchall()
            userList = []
            for i in values:
                # print(i[0])
                userList.append(i[0])

            if usr_name in userList:
                messagebox.showwarning('提示', '用户名已存在!')
            else:
                if usr_pwd == usr_repwd:
                    # 插入数据
                    cursor.execute("insert into user (username,password) values (?,?)", (usr_name, usr_repwd))
                    if (messagebox.showinfo('提示', '注册成功!')):
                        self.root.unbind('<Return>')  # 解绑回车键事件
                        self.register_win_close()
                else:
                    messagebox.showerror('提示', '两次输入的密码不一致!')

            # 关闭Cursor:
            cursor.close()
            # 提交事务:
            conn.commit()
            # 关闭Connection:
            conn.close()
            # 下面返回字符串break使回车绑定事件只触发绑定的方法而不进行默认的换行操作
        return 'break'

因为代码太多我就不直接贴出来了,项目完整源代码上传到我的Github仓库了,可自行下载。下载后安装代码里用到的第三方库,就可直接正常运行项目。

代码地址:https://github.com/ihmily/Python-ChatRoom

注意:先运行服务器端server.py,再运行客户端client.py文章来源地址https://www.toymoban.com/news/detail-508427.html

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

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

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

相关文章

  • 【Linux】基于UDP协议的“聊天室”

    目录 预备知识 基本思路 服务端设计 重要接口详解 服务端核心代码 服务端运行代码 客户端设计 UDP协议(User Datagram Protocal用户数据报协议) 传输层协议 无连接 不可靠传输 面向数据报 如下是我们设计的一个简单的“聊天室”的大致框架图:         “聊天室”分为两个角

    2024年02月20日
    浏览(38)
  • 基于Python web的多人聊天室

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

    2024年02月16日
    浏览(40)
  • 使用Linux系统IO多路复用中eopll创建基于TCP通信协议的多人聊天室

    一.1.搭建好TCP的通信模型 2.创建红黑树根节点 3.将套接字事件添加到红黑树中,使其被监听 4.当套接字事件发生,表示有客户端连接,将连接事件加入到红黑树节点当中 5.每当连接事件发生时,表示客户端发送信息到服务器 6.每当有事件准备就绪时,将对应的红黑树节点信息

    2024年02月13日
    浏览(44)
  • Linux-Socket实现模拟群聊(多人聊天室)

    简单版本 服务端源码 客户端源码 服务器可以在特定的端口监听客户端的连接请求,若连接成功,服务器采用广播的形式向当前所有连接客户端发送该客户端登录成功消息多个客户端可以同时登录,在源码文件中可以配置最多群聊同时在线人数。服务端接收到客户端发送的群

    2024年02月10日
    浏览(93)
  • 基于Python guI的多人聊天室的设计与实现

    现在,即时聊天系统已成为 Internet 上的主要交流工具,并且涌现出大量的AP和平台。这些AP和平台都拥有更加完善的交换机制,使得人们可以更加便捷地进行沟通和交换信息。 广域网的聊天系统多重多样,知名的软件主要有 Facebook、腾讯 QQ 等。局域网聊天通信软件也有很多,

    2024年02月05日
    浏览(53)
  • Python多人聊天室

    链接:https://pan.baidu.com/s/1kzxiLTkvdxGAMgF3SQzcaw?pwd=vb9h 提取码:vb9h 利用socket方式编写一个多人聊天室程序,可以实现多个用户之间的群聊功能,私聊功能,显示当前用户功能 在聊天室程序中增加利用ftp实现文件的上传,下载,删除,查看当前文件功能 在聊天室程序中增加利用

    2024年02月03日
    浏览(59)
  • 基于UDP实现的网络聊天室

    服务器: 客户端: 运行结果:

    2024年03月08日
    浏览(65)
  • QT程序设计多人聊天室(基于QT、sqlite3、TCP/IP)

    目录 技术路线 效果展示 程序主体 sqoperator.h mylogin.h myenroll.h chatinterface.h tips.h myapp.h ******************* sqoperator.cpp mylogin.cpp myenroll.cpp chatinterface.cpp tips.cpp myapp.cpp main.cpp widget.h widget.cpp main.cpp QT程序设计、sqlite数据库调用、TCP/IP客户端与服务端的搭建 通过次程序代码,可以学习如

    2024年02月09日
    浏览(63)
  • 基于Java Socket写一个多线程的聊天室(附源码)

    Socket编程是在TCP/IP上的网络编程,但是Socket在上述模型的什么位置呢。这个位置被一个天才的理论家或者是抽象的计算机大神提出并且安排出来 ​ 我们可以发现Socket就在应用程序的传输层和应用层之间,设计了一个Socket抽象层,传输层的底一层的服务提供给Socket抽象层,S

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

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

    2024年02月08日
    浏览(42)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包