Python+Socket实现多人聊天室,功能:好友聊天、群聊、图片、表情、文件等 您所在的位置:网站首页 狂风暴雨图片表情图片 Python+Socket实现多人聊天室,功能:好友聊天、群聊、图片、表情、文件等

Python+Socket实现多人聊天室,功能:好友聊天、群聊、图片、表情、文件等

2024-07-01 12:48| 来源: 网络整理| 查看: 265

一、项目简介

本项目主要基于python实现的多人聊天室,主要的功能如下:

登录注册添加好友与好友进行私聊创建群聊邀请/申请加入群聊聊天发送图片聊天发送表情聊天发送文件聊天记录保存在本地中聊天过程中发送的文件保存本地 二、环境介绍 python3.8mysql8.0tkinter:作为程序的gui库flask :主要用于登录/注册、表情下载、信息修改等http请求等socket:主要用户聊天过程中消息发送、对方在线状态更新等pygame:用于播放新消息提示音 三、运行展示

登录: 登录页面 注册: image-20220427221842887 登录后主界面: image-20220427221858349 点击右上方“修改资料”: image-20220427221942224 添加好友或群: image-20220427222002416 双击好友或群打开聊天窗口: image-20220427222032094 点击表情按钮选择发送的表情: image-20220427222102584 发送图片可以预览,点击文件名称直接打开: image-20220427222217499

四、关键代码

配置文件:server.conf

配置服务器ip、http端口、socket端口、数据库的账号密码、是否启用新消息提示音

[server] SERVER_IP = 127.0.0.1 HTTP_PORT = 8000 SOCKET_PORT = 8001 SQLALCHEMY_DATABASE_URI = mysql://root:[email protected]:3306/chatdb ENABLE_MUSIC = 0

服务端主要代码:ChatServer.py

维持Socket通信、开启Flask进行http

# controller定义 @app.route('/login', methods=['POST']) def login(): try: params = request.values login_name = params['loginName'] pwd = params['pwd'] md5 = hashlib.md5() md5.update(pwd.encode(encoding='utf-8')) password = md5.hexdigest() users = Users.query.filter(Users.loginName == login_name)\ .filter(Users.pwd == password).all() if len(users) == 0: return Result.fail('账号不存在或密码错误') else: # 服务返回uid,客户端打开好友界面后,凭借此uid与服务器进行socket连接 uid = users[0].id # 已存在uid:已登录,重新登录,原登录退出连接,退出程序 if uid in online_users.keys(): # logout connection = online_users[int(uid)] send_msg = {'type': UtilsAndConfig.SYSTEM_LOGOUT} connection.send(json.dumps(send_msg).encode()) online_users[uid] = None return Result.success(uid) except Exception as e: return Result.fail('参数异常') # 监听socket def socket_listen_thread(): while True: connection, address = mySocket.accept() # 用户连接携带的uid,判断是否和服务器相同 data_dic = json.loads(connection.recv(1024).decode()) uid = None if data_dic['type'] == UtilsAndConfig.CONNECTION_REQUEST: uid = int(data_dic['uid']) else: connection.send(UtilsAndConfig.CONNECTION_NOT_ALLOWED.encode()) if uid in online_users.keys(): # 可建立连接 online_users[uid] = connection connection.send(UtilsAndConfig.CONNECTION_ALLOWED.encode()) # 通知好友们,我上线了 friends = get_friends_by_uid(uid) for f in friends: if f.id in online_users.keys(): friend_connection = online_users[f.id] send_msg = {'type': UtilsAndConfig.FRIENDS_ONLINE_CHANGED, 'uid': uid, 'online': 1} friend_connection.send(json.dumps(send_msg).encode()) # 创建子线程,保持通信 keep_link_thread = threading.Thread(target=socket_keep_link_thread, args=(connection, )) keep_link_thread.setDaemon(True) keep_link_thread.start() else: connection.send(UtilsAndConfig.CONNECTION_NOT_ALLOWED.encode()) def socket_keep_link_thread(connection): while True: try: msg = connection.recv(1024).decode() if not msg: if connection in online_users.values(): uid = list(online_users.keys())[list(online_users.values()).index(connection)] online_users.pop(uid) friends = get_friends_by_uid(uid) for f in friends: if f.id in online_users.keys(): friend_connection = online_users[f.id] send_msg = {'type': UtilsAndConfig.FRIENDS_ONLINE_CHANGED, 'uid': uid, 'online': 0} friend_connection.send(json.dumps(send_msg).encode()) connection.close() return else: msg_json = json.loads(str(msg)) # 发消息 if msg_json['type'] == UtilsAndConfig.CHAT_SEND_MSG: to_id = msg_json['toId'] is_friend = msg_json['isFriend'] from_uid = msg_json['fromId'] send_time = msg_json['sendTime'] msg_text = msg_json['msgText'] data = {'from_uid': from_uid, 'to_id': to_id, 'send_time': send_time, 'msg_text': msg_text, 'is_friend': is_friend, 'type': '', 'msg_type': 'train'} # 通知接收方,收到新消息 if is_friend == 1: if to_id in online_users.keys(): friend_connection = online_users[to_id] data['type'] = UtilsAndConfig.CHAT_HAS_NEW_MSG friend_connection.send(json.dumps(data).encode()) # 通知发送方,发送成功 data['type'] = UtilsAndConfig.CHAT_SEND_MSG_SUCCESS connection.send(json.dumps(data).encode()) else: # 通知发送方,发送失败,对方不在线 data['type'] = UtilsAndConfig.CHAT_SEND_MSG_ERR connection.send(json.dumps(data).encode()) else: # 群 members = get_group_members(to_id) members_online = False for m in members: if m.uId in online_users.keys() and m.uId != from_uid: members_online = True member_connection = online_users[m.uId] data['type'] = UtilsAndConfig.CHAT_HAS_NEW_MSG member_connection.send(json.dumps(data).encode()) if members_online: # 通知发送方,发送成功 data['type'] = UtilsAndConfig.CHAT_SEND_MSG_SUCCESS connection.send(json.dumps(data).encode()) else: # 通知发送方,发送失败,对方不在线 data['type'] = UtilsAndConfig.CHAT_SEND_MSG_ERR connection.send(json.dumps(data).encode()) if msg_json['type'] == UtilsAndConfig.CHAT_SEND_FILE: from_id = msg_json['from_id'] to_id = msg_json['to_id'] is_friend = msg_json['is_friend'] send_date = msg_json['send_date'] file_length = msg_json['file_length'] file_suffix = msg_json['file_suffix'] file_name = msg_json['file_name'] file_save_name = str(uuid.uuid1()) + '.' + file_suffix return_file_path = '/static/tmp/' + file_save_name file_path = os.path.abspath(os.path.dirname(__file__)) + return_file_path if not os.path.exists(os.path.dirname(file_path)): os.makedirs(os.path.dirname(file_path)) data = {'from_uid': from_id, 'to_id': to_id, 'send_time': send_date, 'file_name': file_name, 'is_friend': is_friend, 'type': UtilsAndConfig.CHAT_SEND_FILE_SUCCESS, 'file_path': return_file_path} if is_friend == 1: if to_id not in online_users.keys(): # 通知发送方,发送失败,对方不在线 data['type'] = UtilsAndConfig.CHAT_SEND_MSG_ERR connection.send(json.dumps(data).encode()) continue else: members = get_group_members(to_id) flag = True for m in members: if m.uId in online_users.keys() and m.uId != from_id: flag = False break if flag: # 通知发送方,发送失败,对方不在线 data['type'] = UtilsAndConfig.CHAT_SEND_MSG_ERR connection.send(json.dumps(data).encode()) continue # 接收文件 total_data = b'' file_data = connection.recv(1024) total_data += file_data num = len(file_data) while num


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有