本文来源吾爱破解论坛
本帖最后由 袅袅系秋风 于 2019-9-7 20:16 编辑 1.png (20.21 KB, 下载次数: 0)
下载附件
保存到相册
2.png (59.66 KB, 下载次数: 0)
下载附件
保存到相册
3.png (50.16 KB, 下载次数: 0)
下载附件
保存到相册
4.png (16.86 KB, 下载次数: 0)
下载附件
保存到相册
6.png (289.16 KB, 下载次数: 0)
下载附件
保存到相册
程序目前尚未完全完成,勿喷
如果有错的或者有更简单的方法请留下言,共同学习哈
数据库使用的是mysql、用户为root、密码123456
数据库结构
create database database1;
use database1;
create table user_info(
nickname varchar(20),
id varchar(20) not null,
pwd varchar(20)
);
insert into user_info(nickname,id,pwd)value('用户1','123456789','123456789');
insert into user_info(nickname,id,pwd)value('用户2','987654321','987654321');
程序执行顺序
1、首先运行s.py
2、其次在终端运行“界面.py”登陆账户1(123456789为用户1)
3、其次在另一个终端运行“界面.py”登陆账户2(987654321为用户2)
4、下图是登陆后界面(和谁聊天点谁,目前只能用户1和用户2聊天,如果没有查到用户则将消息保存到消息队列,等到有该用户连接服务器再发送)
5、下方是聊天界面截图
服务端代码
文件名: s.py
[Python] 纯文本查看 复制代码
# -*- coding: UTF-8 -*- import socket from queue import Queue from time import sleep import threading class service: def __init__(self): self.sendMsgQueue = Queue() self.recvMsgQueue = Queue() self.connect_info=[] self.accept_connect=[] self.s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) self.host='127.0.0.1' self.port=2333 def accept_request(self): self.s.bind((self.host, self.port)) self.s.listen(50) while True: print('正在等待连接。。。') conn = self.s.accept() nickname=conn[0].recv(1024).decode()#连接成功先将用户昵称接收 #print('nick:',nickname) self.accept_connect.append(conn) self.accept_connect.append(nickname) print(self.accept_connect) #self.connect_info.append('connectinfo'+'/'+str(conn[1][0])+'/'+str(conn[1][1])+'/'+nickname) #print(self.connect_info) #格式: # connectinfo/192.168.29.1/4318/袅袅兮秋风 for info in self.connect_info:#发送当前连接服务气的所有ip 端口 昵称 conn[0].send(info.encode()) #print(conn[0]) #print(conn[1]) print('连接成功') def sendMsg(self): while True: if self.sendMsgQueue.empty(): #print('发送消息队列为空!!!') sleep(1) else: #print('大小:', self.sendMsgQueue.qsize()) #print('555555555555555',len(self.accept_connect)) flag=False length=int(len(self.accept_connect)/2) #print('length',length) msg=self.sendMsgQueue.get() for i in range(0,int(len(self.accept_connect)/2)): #print(self.accept_connect) #print('等待发送。。。',i) name1=self.accept_connect[int(i*2+1)] name2=msg.split('/')[2] if name1==name2: #print('找到收件人',i) self.accept_connect[int(i*2)][0].send(msg.encode()) #print('转发成功?',i) flag=True break if flag==False: print('未找到该用户!!!') self.sendMsgQueue.put(msg) sleep(1) def add_recvmsg_to_queue(self,conn): print('++++',conn) thread = [0]*100 flag=[0]*100 for j in range(0,100): flag[j]=True while True: i = 0 #print('cccconn:',conn) for k in range(0,len(self.accept_connect)): if i%2!=0: i=i+1 continue #print('conn:',c['conn']) if flag[int(i/2)]==True: #print('鹅鹅鹅鹅鹅鹅饿') #print(self.accept_connect) thread[int(i/2)]=threading.Thread(target=self.recvthread,args=(self.accept_connect[i],)) thread[int(i/2)].start() flag[int(i/2)] =False if not thread[int(i/2)].isAlive(): flag[int(i/2)]=True '''recvmsg = c[0].recv(1024).decode() print('调试:',i) if recvmsg.split('/')[0]=='message':#只接受message类型消息到接收队列 self.recvMsgQueue.put(recvmsg) self.sendMsgQueue.put(recvmsg)''' i=i+1 #print('recv队列大小:',self.recvMsgQueue.qsize()) def recvthread(self,c): recvmsg = c[0].recv(1024).decode() if recvmsg.split('/')[0] == 'message': # 只接受message类型消息到接收队列 self.recvMsgQueue.put(recvmsg) self.sendMsgQueue.put(recvmsg) elif recvmsg.split('/')[0] == 'closeconnect':#断开连接,从self.connect中删除此连接 for i in range(0,len(self.accept_connect)): if self.accept_connect[i][0]==c[0]: a=self.accept_connect.pop(i) b=self.accept_connect.pop(i) print(a,b) print(i,self.accept_connect) print('删除成功') break def recvMsg(self): print('--------') while True: if self.recvMsgQueue.empty(): sleep(1) else: #print('接受队列大小:',self.recvMsgQueue.qsize()) msg=self.recvMsgQueue.get().split('/') #print(msg) print(msg[0]+'\n'+msg[1]+'\t'+msg[2]+'\n'+msg[3]+':\t'+msg[4]) def run(self): #接受连接线程 acceptrequestthread=threading.Thread(target=self.accept_request) # 接收消息线程 recvmsgthread = threading.Thread(target=self.recvMsg) # 添加消息到发送消息队列 addmsgthread = threading.Thread(target=self.add_recvmsg_to_queue, args=(self.accept_connect,)) # 发送消息线程 sendmsgthread = threading.Thread(target=self.sendMsg) acceptrequestthread.start() recvmsgthread.start() sendmsgthread.start() addmsgthread.start() if __name__ == '__main__': client1=service() client1.run()
客户端代码
文件名 :c.py
[Python] 纯文本查看 复制代码
import socket import user import time from queue import Queue import threading import sys from tkinter import END class client: def __init__(self,myuser,friendname): self.myuser=myuser self.friendname = friendname self.sendMsgQueue=Queue() self.recvMsgQueue=Queue() self.s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) self.host='127.0.0.1' self.port=2333 def connect_service(self): self.s.connect((self.host,self.port)) self.s.send(self.myuser.getnickname().encode())#连接成功后将连接者昵称发送至服务器 #print(self.s.recv(1024).decode()) def add_sendmsg_to_queue(self,msg,senduser,recvuser): message=msg if not message: print('消息不能为空') return -1 t = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) msg = 'message'+'/'+ senduser.getnickname() +'/'+recvuser+ '/' + t + '/' + message print(msg) self.sendMsgQueue.put(msg) print(self.sendMsgQueue.qsize()) #消息格式: # message/192.168.1.119/testname/2019-08-12 15:25:37/都看过就欧弟郭德纲 def sendMsg(self): while True: if self.sendMsgQueue.empty(): time.sleep(1) else: #print('大小:',self.sendMsgQueue.qsize()) self.s.send(self.sendMsgQueue.get().encode()) def add_recvmsg_to_queue(self): print('++++') while True: #print('conn:',c['conn']) recvmsg = self.s.recv(1024).decode() if recvmsg.split('/')[0]=='message':#只接受message类型消息到接收队列 self.recvMsgQueue.put(recvmsg) #print('recv队列大小:',self.recvMsgQueue.qsize()) def recvMsg(self): #while True: if self.recvMsgQueue.empty(): print('接受队列为空hhhh') return -1 else: # print('接受队列大小:',self.recvMsgQueue.qsize()) msg = self.recvMsgQueue.get().split('/') # print(msg) #print(msg[0] + '\n' + msg[1] + '\t' + msg[2] + '\n' + msg[3] + ':\t' + msg[4]) #message=msg[0] + '\n' + msg[1] + '\t' + msg[2] + '\n' + msg[3] + ':\t' + msg[4] return msg def close_connect(self):#断开socket连接 msg='closeconnect/' self.s.send(msg.encode()) self.s.close() print('断开连接,程序已退出!!!') #sys.exit() def connectandaddmsgtoqueue(self): self.connect_service() # 添加消息到接收消息队列 addrecvmsgthread = threading.Thread(target=self.add_recvmsg_to_queue) addrecvmsgthread.start() # 发送消息线程 sendmsgthread = threading.Thread(target=self.sendMsg) sendmsgthread.start() def run(self): pass #nickname = '用户1' #self.usertest = user.user(nickname) #self.connect_service() #发送消息线程 #sendmsgthread=threading.Thread(target=self.sendMsg) #sendmsgthread.start() # 接收消息线程 #recvmsgthread = threading.Thread(target=self.recvMsg) #recvmsgthread.start() #添加消息到发送消息队列 #addmsgthread = threading.Thread(target=self.add_sendmsg_to_queue,args=(self.chattingtouser,)) #addmsgthread.start() # 添加消息到接收消息队列 #addrecvmsgthread = threading.Thread(target=self.add_recvmsg_to_queue) #addrecvmsgthread.start() #time.sleep(10) #self.close_connect()
程序界面(客户端只需要执行这个)
文件名:界面.py
[Python] 纯文本查看 复制代码
from tkinter import Tk,Canvas,Button,Entry,Checkbutton,Label,PhotoImage,NW,END,scrolledtext,BooleanVar,StringVar,messagebox from PIL import Image,ImageTk from threading import Thread from time import strftime,sleep,time,localtime import pymysql import c import user #登陆类 class LoginPanel: def __init__(self): #图形界面区域 self.root = Tk() self.root.title('登陆0.0.1') self.root.geometry('450x350+400+200') #头像区域 self.head = Canvas(self.root) #self.head.create_oval(165, 15, 265, 115) self.head.place(x=5, y=5, heigh=120, width=440) #输入区域 self.input = Canvas(self.root, bg='#ffffff') self.input.place(x=5, y=130, heigh=220, width=440) #登陆按钮 self.loginbutton=Button(self.input,text='登陆',bg='#4fcffd',command=self.loginbuttonclickevent) self.loginbutton.place(x=100,y=160,heigh=40, width=240) #账号输入框 self.accountinput=Entry(self.input,font=("仿宋", 16, "bold")) self.accountinput.place(x=130,y=60,heigh=30,width=210,) #密码输入框 self.passwordinput = Entry(self.input,font=("仿宋", 16, "bold"),show='*') self.passwordinput.place(x=130, y=95, heigh=30, width=210) #自动登录checkbutton self.autologinvar=BooleanVar() self.autologincheck=Checkbutton(self.input,text='自动登录',variable=self.autologinvar,command=self.autologincheckbuttonstatusevent) self.autologincheck.place(x=100, y=130, heigh=15, width=80) #记住密码 self.remberpasswordvar=BooleanVar() self.remberpasswordcheck = Checkbutton(self.input, text='记住密码',variable=self.remberpasswordvar,command=self.remberpasswordcheckbuttonstatusevent) self.remberpasswordcheck.place(x=190, y=130, heigh=15, width=80) #找回密码 self.findpasswordbutton=Button(self.input,text='找回密码',bg='white') self.findpasswordbutton.place(x=290, y=130, heigh=15, width=50) #注册账号 self.registerbutton=Button(self.input,text='注册账号',bg='white',command=self.registerbuttonclickevent) self.registerbutton.place(x=10, y=190, heigh=15, width=50) #准备工作 #1、获取复选框状态(自动登录,记住密码) #2、如果自动登录已勾选,获取最近一次登录账号及对应密码输入框并直接登录,摧毁当前窗口,打开主界面窗口, #3、如果仅勾选记住密码,则仅获取最近一次登录账号及对应密码输入框,等待用户操作 #对应事件监听区域 #登录按钮点击事件 def loginbuttonclickevent(self): account = self.accountinput.get().strip().replace(' ', '') self.accountinput.delete(0, END) self.accountinput.insert(END, account) print(account) password = self.passwordinput.get().strip().replace(' ', '') self.passwordinput.delete(0, END) self.passwordinput.insert(END, password) print(password) if len(account) < 8 or len(password) < 8 or not account.isdigit(): messagebox.showinfo('登录失败', '查无此号') return -1 for c in password: if ord(c) > 255: messagebox.showinfo('登录失败', '密码错误\n( ⊙ o ⊙ )') return -2 print('等待连接数据库。。。') db = pymysql.connect('localhost', 'root', '123456', 'database1') cursor = db.cursor() print('连接成功') sql = "select pwd,nickname from user_info where id=%s"%account # print('sql',sql) # cursor.execute("select * from user_info") try: cursor.execute(sql) results=cursor.fetchall()[0] print('results',results) if results[0]==password: messagebox.showinfo('登录成功','登录成功') db.close() self.root.destroy() mainpanel=MainPanel(results[1]) mainpanel.run() return 0 messagebox.showinfo('登录失败','账号密码不匹配') except: print('登录抛出异常') db.rollback() db.close() return -3 #登录操作 #登录成功,自动保存账号,并根据记住密码复选框状态决定是否保存密码 #自动登录勾选事件 def autologincheckbuttonstatusevent(self): print('自动登录状态:',self.autologinvar.get()) #如果为自动登录状态,则记住密码为勾选状态 if self.autologinvar.get()==True: self.remberpasswordvar.set(True) #记住密码勾选事件 def remberpasswordcheckbuttonstatusevent(self): print('记住密码状态:',self.remberpasswordvar.get()) #注册账号按钮点击事件(未完成) def registerbuttonclickevent(self): register = RegisterPanel() register.run() #找回密码按钮点击事件(未完成) def findpasswordbuttonclickevent(self): pass def run(self): self.root.mainloop() pass class MainPanel: def __init__(self,loginnickname): self.myuser=user.user(loginnickname) self.root=Tk() self.root.title('聊天主界面0.0.1') self.root.geometry('350x600+400+50') #个人信息区域 self.head=Canvas(self.root,bg='orange') self.head.create_oval(30,30,80,80) self.head.place(x=5,y=5,heigh=120,width=340) #好友区域 self.frend = Canvas(self.root, bg='pink') self.frend.place(x=5, y=130, heigh=420, width=340) #设置区域 self.setting = Canvas(self.root, bg='yellow') self.setting.place(x=5, y=555, heigh=40, width=340) #好友栏 self.frendstext=scrolledtext.ScrolledText(self.frend) self.frendstext.place(x=5,y=5,heigh=410,width=330) #自己的昵称名标签 self.myselfnicknamelable=Label(self.head,text=self.myuser.getnickname()) self.myselfnicknamelable.place(x=100,y=30) friendnum=10 for i in range(friendnum): Thread(target=self.friendbuttonthread,args=('用户'+str(i+1),)).start() #绑定对应好友事件 def friendbuttonthread(self,friendname): friendbutton=Button(self.frendstext,text=friendname,bg='#ecf3d8',heigh=2,width=44,command=lambda:self.friendsbuttonclickevent(friendname)) self.frendstext.window_create(END, window=friendbutton) #监听事件 #好友按钮点击事件 def friendsbuttonclickevent(self,friendname): print(friendname) self.client=c.client(self.myuser,friendname) #Thread(target=ChatPanel(self.myuser,friendname,self.client).run).start() print('66666666666666') Thread(target=self.client.connectandaddmsgtoqueue).start() print('77777777777777') ChatPanel(self.myuser, friendname, self.client).run() print('88888888888888') #连接数据库,获取好友列表 #每个用户建立一个数据库 #好友信息table 昵称 账号 其他(待补充) def getmyfriendsinfo(self): pass def run(self): self.root.mainloop() class ChatPanel: def __init__(self,myuser,frienduser,client): self.client=client self.root = Tk() self.frienduser=frienduser#暂时未用户名, 不是user对像!!!!!!! self.myuser = myuser self.root.title('登录用户: '+self.myuser.getnickname()) self.root.geometry('700x600+400+50') #标题 self.headtitle = Canvas(self.root, bg='yellow') self.headtitle.place(x=5, y=5, heigh=40, width=690) #好友名字标签 titlenamelable=Label(self.headtitle,text=self.frienduser) titlenamelable.place(x=200,y=5, heigh=30, width=300) #聊天信息 self.chattext = Canvas(self.root, bg='orange') self.chattext.place(x=5, y=45, heigh=400, width=490) #输入区域 self.input = Canvas(self.root, bg='pink') self.input.place(x=5, y=445, heigh=150, width=490) #好友信息区域 self.info = Canvas(self.root, bg='#d9ffb3') self.info.place(x=495, y=45, heigh=550, width=200) #发送按钮 closebutton=Button(self.input,text='发送',command=self.sendbuttonclickevent) closebutton.place(x=400, y=110, heigh=30, width=80) #关闭按钮 closebutton=Button(self.input,text='关闭',command=self.closebuttonclickevent) closebutton.place(x=310, y=110, heigh=30, width=80) #聊天信息框 self.chattextvar=StringVar self.chatscrolltext=scrolledtext.ScrolledText(self.chattext,font=("仿宋", 16, "normal")) self.chatscrolltext.place(x=5,y=5,heigh=390,width=480) # 信息输入框 self.inputchattext = scrolledtext.ScrolledText(self.input, font=("仿宋", 16, "normal")) self.inputchattext.place(x=5, y=5, heigh=100, width=480) #绑定事件区域 def sendbuttonclickevent(self): #获取输入信息 t = strftime("%Y-%m-%d %H:%M:%S", localtime(time())) msg=self.inputchattext.get('0.0',END) self.inputchattext.delete('0.0',END) print(msg) #将消息加入发送消息队列 self.client.add_sendmsg_to_queue(msg,self.myuser,self.frienduser) #将输入信息追加到聊天记录中 self.chatscrolltext.insert(END,t+'\n'+self.myuser.getnickname()+'\t:'+msg) print('发送按钮被点击了') def closebuttonclickevent(self): print('关闭按钮被点击了') self.closewindow() def closewindow(self): self.client.close_connect() self.root.destroy() def recvthread(self): while True: msg=self.client.recvMsg() if msg==-1: sleep(1) continue print('mmmsg',msg) self.chatscrolltext.insert(END, msg[3] + '\n' + msg[1] + '\t:' + msg[4]) print('插入成功') def run(self): # 接收消息线程 #Thread(target=self.client.recvMsg,args=(self.chatscrolltext,)).start() #self.root.mainloop() Thread(target=self.recvthread).start() print('ssssssssssssssssssssss') self.root.mainloop() #Thread(target=self.root.mainloop).start() class RegisterPanel: def __init__(self): self.root = Tk() self.root.title('注册0.0.1') self.root.geometry('450x350+400+200') # 输入区域 self.input = Canvas(self.root, bg='#ffffff') self.input.place(x=5, y=130, heigh=220, width=440) # 注册按钮 self.loginbutton = Button(self.input, text='立即注册', bg='#4fcffd', command=self.registerbuttonclickevent) self.loginbutton.place(x=100, y=160, heigh=40, width=240) # 昵称输入框 self.nicknameinput = Entry(self.input, font=("仿宋", 16, "bold")) self.nicknameinput.place(x=130, y=20, heigh=30, width=210, ) # 账号输入框 self.accountinput = Entry(self.input, font=("仿宋", 16, "bold")) self.accountinput.place(x=130, y=60, heigh=30, width=210, ) # 密码输入框 self.passwordinput = Entry(self.input, font=("仿宋", 16, "bold"), show='*') self.passwordinput.place(x=130, y=95, heigh=30, width=210) def registerbuttonclickevent(self): nickname=self.nicknameinput.get().strip().replace(' ','') self.nicknameinput.delete(0, END) self.nicknameinput.insert(END, nickname) print(nickname) account=self.accountinput.get().strip().replace(' ','') self.accountinput.delete(0,END) self.accountinput.insert(END,account) print(account) password=self.passwordinput.get().strip().replace(' ','') self.passwordinput.delete(0,END) self.passwordinput.insert(END,password) print(password) if len(account)<8 or len(password)<8 : messagebox.showinfo('注册失败','账号或密码过短\no(︶︿︶)o') return -1 if not account.isdigit(): messagebox.showinfo('注册失败','账号必须全为数字\n(╯﹏╰)') return -2 for c in password: if ord(c)>255: messagebox.showinfo('注册失败','密码不能包含非法字符\n( ⊙ o ⊙ )') return -3 print('等待连接数据库。。。') db=pymysql.connect('localhost','root','123456','database1') cursor=db.cursor() print('连接成功') sql="insert into user_info(id,nickname,pwd)value('%s','%s','%s')"%(account,nickname,password) #print('sql',sql) #cursor.execute("select * from user_info") try: cursor.execute(sql) db.commit() except: db.rollback() db.close() messagebox.showinfo('注册成功','恭喜您 注册成功\n~\(≧▽≦)/~') return 0 def run(self): self.root.mainloop() if __name__ == '__main__': loginpanel = LoginPanel() loginpanel.run() #mainpanel=MainPanel() #mainpanel.run() #chatpanel=ChatPanel() #chatpanel.run() #register=RegisterPanel() #register.run()
存储用户信息的类
文件名:user.py
[Python] 纯文本查看 复制代码
import socket class user: def __init__(self,nickname='null'): self.ip=self.get_host_ip() self.nickname=nickname#自己的昵称 self.friends=[]#存储好友信息 #self.friends=[0]*100 def add_friend(self): print(self.ip,self.nickname) def get_host_ip(self): try: s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect(('8.8.8.8', 80)) self.ip = s.getsockname()[0] finally: s.close() return self.ip def getip(self): return self.ip def getnickname(self): return self.nickname
想省事的可以直接从这里下载哦
下载积分: 吾爱币 -1 CB
5.png (18.09 KB, 下载次数: 0)
下载附件 保存到相册
2019-9-7 19:51 上传
版权声明:
本站所有资源均为站长或网友整理自互联网或站长购买自互联网,站长无法分辨资源版权出自何处,所以不承担任何版权以及其他问题带来的法律责任,如有侵权或者其他问题请联系站长删除!站长QQ754403226 谢谢。
- 上一篇: 分享一个键盘记录器
- 下一篇: 每天早上让树莓派叫你起床