如何用Python做一个聊天程序(1)(没废话,超实用!)

如何用Python做一个聊天程序(1)(没废话,超实用!)

以前我用过编程猫的Coco编辑器做过一个聊天App,但感觉不是很爽,处处都要受到限制。于是我按照我在编程猫上的思路,用Python制作了一个聊天程序。

思路

下载一个MySQL数据库,并做好处理。这个数据库相当于整个程序的服务端。

客户端使用tkinter的GUI制作,主要功能包括:收信息,发信息。收发信息的数据储存在MySQL的信息收发数据库。

同时需要在MySQL里创建一个账户管理的数据库,用来储存账号信息,包括账号名,密码,昵称等等。

服务端

MySQL的配置

首先在MySQL官网下载一个MySQL(小白推荐阅读:(70条消息) MySQL安装配置教程(超级详细、保姆级)_SoloVersion的博客-CSDN博客_mysql安装配置)。推荐下载5.7版本,同时建议下载一个Navicat,管理数据的时候更加可视化。

配置完成后在MySQL上开放权限。(“%”表示任何主机均可连接你的数据库)

(提示:Windows用户该权限放开后无法连接大概率是防火墙问题,在防火墙的入站规则中将你的MySQL端口(默认3306)设为通过)。

(Linux系统大概率是MySQL文件夹的my.cnf的bind_address的值为127.0.0.1,首先将MySQL服务关闭,然后将127.0.0.1改为0.0.0.0,启动,但这样会有非常大的风险,有可能会导致数据库无法启动,不建议操作!)。

grant all privileges on *.* to root@'%' identified by '你的密码' with grant option;

flush privileges;

创建数据库。(先将数据库,表,以及行改为utf-8,否则无法插入中文)

create database 你的数据库名;

创建表

create table 账号管理(账号名 bigint, 密码 varchar(20), 昵称 varchar(20);

create table 主服务器(发送人账号 bigint, 发送人昵称 varchar(20), 发送内容 varchar(20000), 收件人账号 bigint, 已读未读 int(1));

这个时候服务器所在的局域网的所有主机都可以通过服务器所在的主机的IP地址连接上服务器,但这远远不够,我们需要全球任何一个角落的人都可以连接上这台服务器。

内网映射

这个时候我们需要下载一个叫“花生壳”的工具。

打开“花生壳”,注册账号。点击加号。

进入花生壳官网,填写数据。

应用名称

自定义,一般写个有含义的名称

应用图标

可以给对应的服务选择一个图标,方便区分

映射类型

选择TCP

外网域名

选择帐号下的壳域名作为外网访问地址

外网端口

选择动态端口

内网主机

填写服务器的局域网IP地址

内网端口

3306(若内网数据库为SqlServer则是1433)

带宽

默认根据帐号等级分配相应的带宽,也可根据实际需求额外付费购买

夜间带宽

18:00-次日8:00带宽速度提升100%,速度不低于5Mbps;带宽基数越大,夜间越快

点击“保存”即可。

完成后使用Navicat尝试连接。

这个时候天南海北的人都可以通过该IP连接数据库。

客户端

准备

Python 3.x(推荐使用Pycharm)

配置好的MySQL数据库

导入库(在cmd中用pip导入)

pip install pymysql

pip install threading

GUI框架

这里使用Python自带的tkinter(作者也是初次接触,太复杂的GUI我也不会😶)

from tkinter import *

def main():

win = Tk()

win.title('登录')

win.geometry('400x400')

win.resizable(False, False)

win.config(background='light gray')

Label(win, text='登录', bg='light gray', font=('楷体', 32), fg='black').pack()

Label(win, text='账号', bg='light gray', font=('微软雅黑', 15), fg='black').place(x=30, y=120)

Label(win, text='密码', bg='light gray', font=('微软雅黑', 15), fg='black').place(x=30, y=180)

e1 = Entry(win, width=35, relief=FLAT)

e2 = Entry(win, width=35, show='*', relief=FLAT)

e1.place(x=100, y=126)

e2.place(x=100, y=186)

def sign_in():

# 登录验证

pass

def sign_up():

# 注册账号

root = Tk()

root.title('注册')

root.geometry('400x400')

root.resizable(False, False)

root.config(background='light gray')

Label(root, text='注册', bg='light gray', font=('楷体', 32), fg='black').pack()

Label(root, text='账号', bg='light gray', font=('微软雅黑', 15), fg='black').place(x=30, y=120)

Label(root, text='密码', bg='light gray', font=('微软雅黑', 15), fg='black').place(x=30, y=180)

Label(root, text='昵称', bg='light gray', font=('微软雅黑', 15), fg='black').place(x=30, y=240)

e11 = Entry(root, width=35, relief=FLAT)

e22 = Entry(root, width=35, show='*', relief=FLAT)

e33 = Entry(root, width=35, relief=FLAT)

e11.place(x=100, y=126)

e22.place(x=100, y=186)

e33.place(x=100, y=246)

def signup():

# 注册详情

pass

Button(root, text='注册', bg='green', fg='white', command=signup, width=10, height=1, relief=RIDGE).pack(side='bottom', pady=60)

Button(win, text='点击注册', bg='light gray', fg='blue', command=sign_up, width=10, height=1, relief=FLAT).pack(side='bottom')

Button(win, text='登录', bg='green', fg='white', command=sign_in, width=10, height=1, relief=RIDGE).pack(side='bottom', pady=90)

if __name__ == '__main__':

main()

客户端+服务器

我们使用Python的pymysql库,它可以很方便得连接MySQL数据库。

使用详情参考:(70条消息) pymysql的使用教程_Andy86666的博客-CSDN博客_pymysql

验证账号

验证账号的具体思路是:

连接服务器。

获取输入的手机号。

与数据库中现有的手机号进行比对,比对成功下一步,不成功直接弹窗“该账号不存在!”。

获取该账号的信息,如昵称,手机号,密码等。

对比输入密码与数据库存在密码,相同则成功登录,不同就弹窗“密码错误”。

具体代码如下:

def sign_in():

# 验证账号

try:

conn = pymysql.connect(host='刚刚映射的IP', port=刚刚映射的端口, user='用户名', password='你的MySQL密码', database='数据库名称')

cursor = conn.cursor()

try:

sql1 = 'select * from 账号 where 手机号=' + str(e1.get())

cursor.execute(sql1)

global all1

all1 = cursor.fetchone()

conn.close()

cursor.close()

if all1 == None:

messagebox.showerror('学霸小鼠', '该账号不存在!')

else:

passw = all1[2]

if e2.get() == passw:

messagebox.showinfo('学霸小鼠', '登录成功')

win.destroy()

# f2.start()(整体代码需要)

else:

messagebox.showerror('学霸小鼠', '密码错误!')

except:

messagebox.showerror('学霸小鼠', '请检查输入!')

except:

messagebox.showerror('学霸小鼠', '服务器未开放!')

注册账号

思路:

通过GUI的方式获取用户所要注册的账号,信息包括手机号,昵称,密码。

判断是否符合规则,例如:手机号是否符合MySQL的bigint(不符合就会报错),建立二次填写密码机制,防止填写错误。这里可以用try...except...语句。

判断完成后将数据上传至数据库储存,注册完毕。

代码如下:

try:

conn = pymysql.connect(host='xx.xx.xx.xx', port=xxxxx, user='xxxx', password='xxxxx',database='xxxxx')

cursor = conn.cursor()

cursor1 = conn.cursor()

try:

sql2 = "select * from 账号 where 手机号=" + str(e11.get())

cursor.execute(sql2)

all2 = cursor.fetchone()

if all2 == None and e22.get() == e44.get():

sql3 = "insert into 账号 values('" + str(e33.get()) + "', " + str(e11.get()) + " ,'" + str(e22.get()) + "');"

# print(sql3)

cursor1.execute(sql3)

conn.commit()

messagebox.showinfo('学霸小鼠', '注册成功!')

cursor1.close()

cursor.close()

conn.close()

root.destroy()

else:

messagebox.showwarning('学霸小鼠', '错误!(该账号已注册或您两次输入的密码不一致!)')

except:

messagebox.showerror('学霸小鼠', '请检查输入!')

except:

messagebox.showerror('学霸小鼠', '服务器未开放!')

运行

发送界面

大致框架

左边做一个Text收件箱,右边做一个Text发件箱。(左边只读,右边可改)

三个按钮:刷新、发送、清空聊天记录。

两个滑动块,一左一右。

发送端

思路:

获取GUI界面的输入信息,对比收件人账号与服务器账号,有此账号继续,无此账号禁止发送(防止垃圾信息过多,导致服务器臃肿)。

尝试将信息传输至服务器,成功则完成,不成功报错。传输内容如下:(我定义的已读未读中,0代表未读,1代表已读,发送时自动将信息标记为0)

def send():

try:

conn = pymysql.connect(host='xx.xx.xx.xx', port=xxxx, user='xxxx', password='xxxx', database='xxx')

cursor = conn.cursor()

sql5 = 'select * from 账号 where 手机号={}'.format(e4.get())

cursor.execute(sql5)

all2 = cursor.fetchone()

if all2 == None:

messagebox.showerror('学霸小鼠', '没有此收件人,请检查!')

else:

try:

sql4 = "insert into 内容 values('{}', '{}', {}, {}, '{}', {})".format(e3.get('1.0', 'end'), all1[0], all1[1], e4.get(), time.ctime(), 0)

cursor.execute(sql4)

conn.commit()

cursor.close()

conn.close()

messagebox.showinfo('学霸小鼠', '发送成功!')

except:

messagebox.showerror('学霸小鼠', '发送失败!请检查信息!')

except:

messagebox.showerror('学霸小鼠', '未知错误!请联系管理员解决!')

接收端

思路:

实时比对当前手机号是否存在与发送数据库的“收件人账号”中,存在则输出。

输出的内容是一组元组,需要进行简单处理。

处理完毕后提取相关信息,插入到收件箱上。

将已读未读标记为1,防止下一轮循环中再次插入。

def receive():

try:

e5.configure(state='normal')

e5.delete('1.0', END)

# we = '{}的收信箱:\n\n'.format(all1[0])

# e5.insert(INSERT, we)

conn = pymysql.connect(host='', port=49657, user='root', password='zhang2008', database='mindchat')

cursor = conn.cursor()

sql6 = 'select * from 内容 where 收件人账号={}'.format(all1[1])

cursor.execute(sql6)

all8 = cursor.fetchall()

for t in all8:

e5.insert('end', '{}\n{}({})发送的内容\n{}\n\n\n'.format(t[4], t[1], t[2], t[0]))

sql11 = 'update 内容 set 已读未读=1 where 收件人账号={}'.format(all1[1])

cursor.execute(sql11)

conn.commit()

e5.configure(state='disabled')

conn.close()

cursor.close()

except:

messagebox.showerror('学霸小鼠', '未知错误!请检查数据或联系管理员!')

这可以与刷新按钮绑定,但无法实时刷新。

实时通讯

思路

写一个while循环,重复捕捉(同上),间隙为5秒(否则GUI会闪动十分严重)

插入。

def main3():

try:

while True:

e5.configure(state='normal')

# e5.delete('1.0', END)

conn = pymysql.connect(host='xxx', port=xx, user='xx', password='xxxx', database='xxxx')

cursor = conn.cursor()

sql6 = 'select * from 内容 where 收件人账号={} and 已读未读=0'.format(all1[1])

cursor.execute(sql6)

all2 = cursor.fetchall()

# print(all2)

for t in all2:

e5.insert('end', '{}\n{}({})发送的内容\n{}\n\n\n'.format(t[4], t[1], t[2], t[0]))

sql11 = 'update 内容 set 已读未读=1 where 收件人账号={}'.format(all1[1])

cursor.execute(sql11)

conn.commit()

e5.configure(state='disabled')

time.sleep(5)

conn.close()

cursor.close()

zh.update()

except:

pass

清理聊天记录

思路:

新建一个按钮,与接下来的程序绑定。

当点击按钮时,删除数据库中“收件人”=当前手机号的信息。

刷新即可。

def clear():

try:

conn = pymysql.connect(host='xx', port=xx, user='xxx', password='xxxxx', database='xxxxx')

cursor = conn.cursor()

sql9 = 'delete from 内容 where 收件人账号 = {}'.format(all1[1])

cursor.execute(sql9)

conn.commit()

messagebox.showinfo('学霸小鼠', '已清空您的聊天数据!')

cursor.close()

conn.close()

except:

messagebox.showerror('学霸小鼠', '服务器未开放!')

总结

我们利用Python+MySQL开发了一款实时聊天工具,喜欢的话可以加一下关注,以后我会继续发文更新,对程序进行进一步的完善。如果有什么建议可以在评论区输入你的想法。

再见!

相关文章