针对之前很多同学问我这个可不可以支持数据库及增加注册功能,我增加了这些功能,本软件基于python gui图形库pyqt5编写的仿qq,采用mysql数据库存储,socket通信(tcp协议)实现,支持多账号登录,注册,单人私聊,群聊,添加好友分组等功能。
一.主要功能效果展示
登录功能:
注册功能:
单人对聊:
群聊:
二.源码解析
1.项目目录结构
(1)客户端界面目录文件:pyqt5-qq,服务端目录文件:Tcpserver
(2)服务端目录结构
common:存放公共的工具类代码文件目录,主要是配置文件解析工具类,数据库操作工具类,本软件主要使用的是sqlalchemy orm数据库框架。
configfile:存放配置文件目录
dto:存放数据库表模型类代码文件
tcpserver:存放服务端启动及实现逻辑代码文件
(3)客户端目录结构
image,res:存放资源文件
其他文件:界面及逻辑实现源码
2.运行软件
由于使用的是socket通信tcp协议,必须先启动服务端,客户端才能连接服务使用。
服务端启动:运行服务端tcpserver目录下的TcpServer.py文件即可启动,启动前必须要在configfile目录的配置文件配置好数据库连接信息且数据库能正常使用(最好是mysql数据库,其他数据库需要自己更改代码)才能运行成功,运行会自动连接数据库检测是否创建有数据表如何没有会自动创建数据表,需要自己往表里添加一些qq数据信息。
客户端启动:运行login.py文件即可启动
3.模块功能代码解读
服务端启动TcpServer.py源码:
from TcpCase import tcpSocket
import socket
from threading import Thread
from QQTcpServerLogin import QQTcpLogin
from common.sqlalchemyUtil import SqlSession,UserGroupRelation
class TcpServer:
socketList = {}
onlineSocket={}
sqlSession = SqlSession().getSession()
def startTcpServer(self):
print("TcpServer is starting")
while True:
cSocket,ipAdress=tcpSocket.accept()
print("--recv socket connect request:" + str(cSocket) + " ip:" + str(ipAdress))
self.socketList[ipAdress]=cSocket
try:
Thread(target=self.socketThread,args=(cSocket,ipAdress)).start()
except Exception as e:
print("--clietn socket:"+str(cSocket)+" ip:"+str(ipAdress)+" is unusal/unconnet!")
print("Exception:"+str(e))
print("--all socket connect:"+str(self.socketList))
self.socketClose()
def socketThread(self,clientsock,clientaddress):
while True:
group=[]
recvMsg=clientsock.recv(1024).decode('utf-8').split(" ")
msgIdentifcation=recvMsg[0]
#print(msgIdentifcation+" :"+str(type(recvMsg)))
if not recvMsg:
self.socketList.pop(clientaddress)
print("qq已下线!")
elif msgIdentifcation=='login':
login=QQTcpLogin()
res=login.loginCheck(recvMsg[1],recvMsg[2])
if res=="true":
self.onlineSocket[recvMsg[1]]=clientsock
print(recvMsg[1]+" is login success")
clientsock.send(res.encode())
elif msgIdentifcation=='personal':
print("private msg:"+str(recvMsg))
self.privateMessage(recvMsg[2],recvMsg[1]+":"+recvMsg[3],clientsock)
elif msgIdentifcation == 'groupchat':
print("group msg:" + str(recvMsg))
self.groupMessage(recvMsg[1],recvMsg[2]+":"+recvMsg[3])
elif msgIdentifcation=='register':
login = QQTcpLogin()
resgisterRes = login.register(recvMsg[1],recvMsg[2])
clientsock.send(resgisterRes.encode())
else:
print("收到信息:"+str(recvMsg)+" 此信息无法识别!")
def socketClose(self):
return tcpSocket.close()
def privateMessage(self,accepter,sendMsgs,cSocket):
try:
print(str(self.onlineSocket.get(accepter))+accepter)
if self.onlineSocket.get(accepter):
self.onlineSocket[accepter].send(sendMsgs.encode())
cSocket.send(sendMsgs.encode())
else:
msg=accepter+" 不在线!"
cSocket.send(msg.encode())
except Exception as e:
print("private chating exception" +e)
def groupMessage(self,group,sendMsgs):
try:
group_qqs=self.sqlSession.query(UserGroupRelation).filter(UserGroupRelation.group_name==group).all()
for relatoin in group_qqs:
if self.onlineSocket.__contains__(relatoin.user_qq):
self.onlineSocket[relatoin.user_qq].send(sendMsgs.encode())
else:
print(group+" member " +relatoin.user_qq+ " isn't online!")
# print(group_qqs)
except Exception as e:
print("Group chating exception" +str(e))
if __name__=='__main__':
if SqlSession().initDB():
TcpServer().startTcpServer()
else:
print("TcpServer start failed! The reason is mysql no runing ")
代码实现逻辑都比较简单,需要最新项目代码或有问题不懂可以在csdn博客提问我。