{"id":18285782,"url":"https://github.com/wxxshirley/chatroom","last_synced_at":"2025-07-10T18:36:57.285Z","repository":{"id":85288373,"uuid":"235789505","full_name":"WxxShirley/Chatroom","owner":"WxxShirley","description":"💻基于socket网络聊天室,计算机网络课程pj。v2.0多人群聊,好友间私聊","archived":false,"fork":false,"pushed_at":"2020-05-23T07:32:15.000Z","size":2633,"stargazers_count":8,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-16T03:10:18.415Z","etag":null,"topics":["chatroom","socket-programming","tkinter-gui"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/WxxShirley.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-01-23T12:22:52.000Z","updated_at":"2025-05-12T05:54:20.000Z","dependencies_parsed_at":"2023-06-05T14:45:26.478Z","dependency_job_id":null,"html_url":"https://github.com/WxxShirley/Chatroom","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/WxxShirley/Chatroom","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WxxShirley%2FChatroom","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WxxShirley%2FChatroom/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WxxShirley%2FChatroom/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WxxShirley%2FChatroom/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/WxxShirley","download_url":"https://codeload.github.com/WxxShirley/Chatroom/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WxxShirley%2FChatroom/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264631330,"owners_count":23640947,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chatroom","socket-programming","tkinter-gui"],"created_at":"2024-11-05T13:17:43.011Z","updated_at":"2025-07-10T18:36:57.242Z","avatar_url":"https://github.com/WxxShirley.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Chatroom\n计算机网络课程pj，基于socket的网络聊天室。\n\n## 环境\n* python 3.7\n* tkinter\n\n## 运行方法\n* 初始化数据库,执行```database.py```文件中的```init_database()```函数(`main`中其他要注释)\n* 启动服务端\n  ```python server.py```\n* 再启动客户端\n  ```python client.py```\n  客户端可并行\n\n## 功能 version2.0\n目前已经实现的功能有：\n\n- [x] 所有界面使用tkinter\n- [x] 所有用户信息、聊天信息、好友关系、好友间私聊信息存储于sqlite数据库中\n- [x] 用户可以注册账号、登陆\n- [x] 一台电脑可以同时登陆多个用户\n- [x] 登陆后即进入多人群聊界面，支持多人群聊\n- [x] 多人群聊可发送文本信息、表情符号(emoji)、文件(不超过50M）\n- [x] 多人群聊显示最近**5**条聊天记录和所有已经传送的文件\n- [x] 多人群聊显示所有在线用户\n- [x] 新用户加入或退出多人聊天室时有提醒\n- [x] 多人聊天室信息颜色三类，分别显示**用户自己发送的消息**，**系统消息**，**其他用户发送的消息**\n- [x] 用户可下载所有其他用户上传的文件\n- [x] 用户可通过输入好友名的方式添加好友\n- [x] 好友间可以私聊，所有私聊信息缓存\n- [x] 添加好友时被添加方若在线，收到消息提示\n- [x] 好友间私聊时，另一方若在线，自动弹出聊天界面\n\n## 协议设计\n**客户端**\n\n 编号 | 助记符 | 消息体格式 | 应用场景 \n-|-|-|-\n 1 | LOGIN | ``` str(LOGIN) + username + \"\\r\\n\" + pwd ``` | 用户登陆 \n 2 | REGISTER | ``` str(REGISTER) + user + \"\\r\\n\" + pwd ``` | 用户注册 \n 3 | SEND_MESSAGE | **header** :```str(SEND_MESSAGE) + \"\\r\\n\" + str(len(text))```, **content**:```send_text``` | 多人群聊中用户发送消息\n 4 | GET_ALL_USERS | ```str(GET_ALL_USERS)``` | 登陆多人聊天室后获得当前所有在线用户 \n 5 | GET_ALL_CHAT_HISTORY | ```str(GET_ALL_CHAT_HISTORY) + username``` | 登陆多人聊天室后获得所有历史聊天记录 \n 6 | SEND_EMOJI | **header** :```str(SEND_EMOJI) + \"\\r\\n\" + str(len(emoji))```,**content**: ```emoji``` | 多人群聊中用户发送表情符号 \n 7 | SEND_FILE | **header** : ```file_info = str(SEND_FILE) + receiver + \"\\r\\n\" + filename + \"\\r\\n\" +str(file_size)```, **content** : ```file content``` | 多人群聊中用户发送文件 \n 8 | GET_ALL_FILE_HISTORY | ```str(GET_ALL_FILE_HISTORY)``` | 登陆多人聊天室后获得所有发送文件的历史记录 \n 9 | ADD_FRIEND | **header**:```str(ADD_FRIEND)```,**content**:```source_user+\"\\r\\n\"+target_user``` | 添加好友\n 99 | DOWNFILE | **header**:```str(DOWNFILE)```,**content**:```username+\"\\r\\n\"+filename``` | 用户下载任意多人群聊中已经上传的文件\n 98 | PRIVATE_INIT | **header**:```str(PRIVATE_INIT) + username + \"\\r\\n\" + friend_name``` | 获得用户与```friend_name```间的所有聊天记录\n 0 | SHOW_ALL_FRIENDS | **header**:```str(SHOW_ALL_FRIENDS)```,**content**:```username``` | 获得用户所有好友名\n\n\n**服务端**\n\n 编号 | 助记符 | 应用场景 \n -|-|-\n 101 | LOGIN_SUCCESS | 用户登录成功\n 102 | LOGIN_WRONG_PWD | 用户登录时密码错误\n 103 | LOGIN_ACCOUNT_NOT_EXIST | 用户登录时账号不存在\n 104 | LOGIN_DUPLICATE |登陆时账号重复\n 105 | LOGIN_USERNAME | 用户登录时以广播方式通知所有其他用户\n 201 | REGISTER_SUCCESS | 注册新账号成功\n 202 | REGISTER_ERROR | 注册新账号失败\n 301 | SEND_MESSAGE_ALL | 多人聊天室中发送消息成功\n 302 | SEND_MESSAGE_ERROR | 多人聊天室中发送消息失败\n 303 | SEND_MESSAGE_PER | 好友间私聊时对方在线，成功发送消息\n 304 | SEND_MESSAGE_PER_STORE | 好友间私聊时对方不在线，消息缓存到双方的聊天记录中\n 404 | GET_USERS_ERROR | 获取所有在线用户的用户名失败\n 401 | GET_SUCCESS | 成功获取所有在线用户的用户名\n 501 | RET_HISTORY_SUCCESS | 成功获取多人聊天室中所有聊天记录\n 502 | RET_HISTORY_ERROR | 获取多人聊天室中所有聊天记录失败\n 601 | SEND_EMOJI_SUCCESS | 成功发送表情符号\n 602 | SEND_EMOJI_ERROR | 发送表情符号失败\n 701 | SEND_FILE_SUCCESS | 成功发送文件\n 702 | SEND_FILE_ERROR | 发送文件失败\n 801 | RET_ALL_FILES_SUCCESS | 成功获取所有发送的文件名\n 802 | RET_ALL_FILES_ERROR | 获取所有发送的文件名失败\n 800 | LOGOUT_INFO | 用户登出时以广播方式通知所有其他用户\n 901 | ADD_FRIEND_SUCCESS | 成功添加好友 \n 902 | ALREADY_ADD_ERROR | 添加好友错误：与对方已经是好友关系\n 903 | USERNAME_NOT_EXIST | 添加好友错误：输入的用户名不存在\n 904 | ADD_FRIEND_ERROR | 添加好友错误：其他异常错误\n 905 | ADD_FRIEND_REMIND | 新好友提示：在线时收到其他用户的好友请求\n 290 | DOWNFILE_SUCCESS | 成功下载多人群聊中的文件\n 291 | DOWNFILE_ERROR | 下载多人群聊中的文件失败\n 292 | PRIVATE_INIT_SUCCESS | 成功获得用户与某一好友所有聊天记录\n 293 | PRIVATE_INIT_NONE | 用户与某一好友间聊天记录为空\n 294 | PRIVATE_INIT_ERROR | 获取用户与某一好友所有聊天记录发送错误\n 295 | SHOW_FRIENDS_SUCCESS | 成功获取用户的所有好友名\n 296 | SHOW_FRIENDS_ERROR | 获取用户的所有好友发生错误\n 297 | NO_FRIENDS | 用户暂无好友\n\n\n 在设计的时候不足之处\n * 复用性考虑不足\n \n   用户登陆成功后，需要首先获得聊天记录信息缓存、所有文件、该用户所有好友、与好友间聊天记录，\n   这些是分别用**多个服务端请求**实现。其实可以**简化为一个请求**\n * 安全性考虑不足。\n   * 尚未实现协议加密\n   * 数据完整性缺乏考虑。即便有的协议在头部包括了数据长度，在接受时也未判断接受的数据长度与实际长度是否一致。\n   * 数据库中聊天记录未加密\n\n\n## 整体架构\n### 数据库关系模式\n* 用户信息 - 用户名、密码\n  ```sql\n     CREATE TABLE USERINFO\n       (USERNAME TEXT PRIMARY KEY NOT NULL,\n       PASSWORD TEXT NOT NULL);\n  ```\n  \n* 聊天信息 - ID、发送方、时间、内容\n  ```sql\n     CREATE TABLE GROUP_CHAT_HISTORY\n         ( ID TEXT PRIMARY KEY NOT NULL,\n           SOURCE_USER TEXT NOT NULL,\n           TIME DATETIME NOT NULL,\n           CONTENT TEXT NOT NULL,\n           FOREIGN KEY (\"source_user\") REFERENCES userinfo(\"username\")\n         );\n   ```\n\n* 文件信息 - ID、发送方、时间、文件名、文件内容\n  ```sql\n     CREATE TABLE GROUP_FILE_HISTORY\n        (ID TEXT PRIMARY KEY NOT NULL,\n         SOURCE_USER TEXT NOT NULL,\n         TIME DATETIME NOT NULL,\n         FILENAME TEXT NOT NULL,\n         FILECONTENT TEXT NOT NULL,\n         FOREIGN KEY (\"source_user\") REFERENCES userinfo(\"username\")\n         );\n  ```\n\n* 好友关系 - 用户1，用户2\n  ```sql\n  CREATE TABLE FRIENDS\n    ( USERNAME1 TEXT NOT NULL,\n      USERNAME2 TEXT NOT NULL,\n      PRIMARY KEY (USERNAME1,USERNAME2),\n      FOREIGN KEY (\"username1\") REFERENCES userinfo(\"username\")\n      FOREIGN KEY (\"username2\") REFERENCES userinfo(\"username\")\n    )\n  ```\n  \n*  好友间聊天记录 - ID、发送方、接收方、时间、内容\n   ```sql\n   CREATE TABLE HISTORY_PRIVATE_CHAT\n    ( \"id\" INTEGER not NULL,\n      \"target_user\" TEXT not NULL,\n      \"source_user\" TEXT not NULL,\n      \"time\" DATETIME not NULL,\n      \"text\" TEXT not NULL,\n      PRIMARY KEY(\"id\"),\n      FOREIGN KEY (\"target_user\") REFERENCES \"userinfo\"(\"username\")\n      FOREIGN KEY (\"source_user\") REFERENCES \"userinfo\"(\"username\")\n    );\n   ```\n\n \n ### socket通信\n ``` method.py ```中包含以下socket方法\n * send - 发送消息（utf-8编码）格式，参数为socket, 消息头部, 消息内容\n   ```python\n   def send(socket,header,msg = b\"\"):\n    byte_msg = bytes(header+\"\\n\\n\",encoding = 'utf-8') + msg\n    socket.sendall(byte_msg)\n   ```\n\n* receive - 接收消息，根据```\\n\\n```分割头部和消息，utf-8解码后返回\n  ```python\n  def receive(sock):\n    data = sock.recv(1024)\n    for i in range(len(data)-1):\n        if data[i] == 10 and data[i+1] == 10 : #\"\\n\\n\"分割头部和消息\n            header = data[:i].decode(\"utf-8\")\n            rest = data[i+2:].decode(\"utf-8\")\n            return header, rest\n    return data.decode(\"utf-8\"),\"\"\n  ```\n  \n* 文件处理\n  * **read_file(file_path)** 读取文件\n  * **upload_file(sock,file_path,receiver)** 发送文件信息\n  \n\n### 服务端逻辑\n* 监听多个连接\n  ```python\n    reads, writes, errors = select.select(connections,[],[])\n    for cur in reads:\n        if cur == sock: #new connection\n              ···\n        else : # old connection\n              ···\n              try :\n                   data, rest = receive(cur)\n               except Exception as e:\n                    release(cur) # release this connection\n                    continue\n               handle(cur,data,rest) # handle client's request\n   ```\n\n* handle函数处理\n  对消息头部进行分割，判断消息类型并进行相应处理\n  ```python\n  def handle(conn, msg, rest):\n    state = \"\"\n    try:\n        type = int(msg[0])\n    except Exception as e:\n        print(\"!! wrong request\",e)\n        send(conn,str(WRONG_MESSAGE))\n        return\n\n    if type == REGISTER:\n       ···\n    elif type == LOGIN:\n       ···\n    ···   \n\n  ```\n\n### 客户端逻辑\n用户端开启时进入登陆界面，第一次进入欢迎界面时，与服务端连接并建立会话.登陆成功后，开启监听服务端发来的数据。\n ```python\n sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)\n    try:\n        sock.connect((HOST,PORT))\n        print(sock)\n    except:\n        print(\"Fail to connect (%s,%s)\"%(HOST,PORT))\n ```\n* 初始化界面为登陆，可选择 **登陆** / **注册**\n* 登陆成功后初始化\n  * 获取所有在线用户\n  * 获取所有历史聊天记录\n  * 获取所有历史发送文件\n  * 获取该用户所有好友\n  * 获取该用户与好友间聊天记录\n* 开启服务端数据监听\n  ```python\n  _thread.start_new_thread(listener,(sock,window))\n  ```\n  其中```listener```函数与```handle``` 类似，针对不同协议编号进行处理\n  \n  ```python\n  def listener(sock,root):\n    print(\"?? then ??\")\n    listen_this = [sock]\n\n    while True:\n        reads, writes, errors = select.select(listen_this,[],[])\n                    ···\n                msg_type = data[:3]\n                if msg_type == str(LOGIN_USERNAME):\n                  ···\n                elif msg_type == str(SEND_MESSAGE_ALL):\n                  ···\n      ······              \n  ```\n\n### 文件结构\n\n```xml-dtd\n└  client.py    % 客户端\n└  server.py    % 服务端\n└  constant.py  % 协议编号\n└  method.py    % socket方法，包括send\\receive等\n└  events.py    % 客户端部分事件函数\n└  database.py  % 数据库操作函数\n```\n\n\n## 运行截图\n* 运行 ```client.py``` 初始界面\n ![welcome](https://github.com/WxxShirley/Chatroom/blob/master/imgs/welcome.png)\n \n* 点击注册\n ![register](https://github.com/WxxShirley/Chatroom/blob/master/imgs/register.png)\n \n* 多人聊天室主界面\n  * 显示多人群聊中的近**5**条聊天聊天信息，系统消息（其他用户登陆/登出），其他用户发送的消息，以不同颜色区分\n  * 多人聊天室可传送文件、表情符号、文本\n    * tkinter无法显示emoji，因此我采用诸如 **[emoji-cake]** 的形式来表征一个emoji，目前可以发送的emoji较少，后期会再拓展。\n  * 以列表```Listbox```形式显示\n    * 当前所有在线用户\n      * 随着**其他用户的登录/登出**而更新\n    * 该用户所有好友\n      * 点击“+”即可添加新好友\n      * 随其他用户增加该用户为好友/该用户添加新好友而更新\n      * 双击好友名可展开私聊\n    * 所有多人群聊中已传送的文件\n      * 用户双击文件名即可下载\n      * 随用户上传新文件而更新 \n  ![main_page](https://github.com/WxxShirley/Chatroom/blob/master/imgs_v2.0/mainPage.png)\n \n* 添加好友\n  * 用户输入想要添加好友的用户名，如果添加成功、另一方恰好在线，双方都有消息提示\n  * 否则根据 **用户名不存在** 、 **已经是好友关系** 、 **其他异常错误** 等发送错误信息给用户\n  ![add_friend1](https://github.com/WxxShirley/Chatroom/blob/master/imgs_v2.0/add_friend1.png)\n  ![add_friend2](https://github.com/WxxShirley/Chatroom/blob/master/imgs_v2.0/add_friend2.png)\n  ![add_friend3](https://github.com/WxxShirley/Chatroom/blob/master/imgs_v2.0/add_friend3.png)\n\n* 好友间私聊\n  * 双击好友名即可开始私聊\n  * 目前仅支持文本信息\n  * 所有聊天记录缓存\n  * 若私聊的另一方也在线，发送私聊信息后另一方也会弹出对话信息\n  ![friend_chat](https://github.com/WxxShirley/Chatroom/blob/master/imgs_v2.0/private_chat.png)\n  ![friend_chat1](https://github.com/WxxShirley/Chatroom/blob/master/imgs_v2.0/private_chat2.png)\n  ![friend_chat2](https://github.com/WxxShirley/Chatroom/blob/master/imgs_v2.0/private_chat3.png)\n\n* 文件下载\n  * 双击文件名即可下载\n  ![dowfile](https://github.com/WxxShirley/Chatroom/blob/master/imgs_v2.0/down_file.png)\n  \n  \n  \n## 未来工作\n待完善的功能 \n- [ ] 创建群组，实现群聊\n \n \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwxxshirley%2Fchatroom","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwxxshirley%2Fchatroom","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwxxshirley%2Fchatroom/lists"}