# ChatRoom **Repository Path**: XiangFugui/ChatRoom ## Basic Information - **Project Name**: ChatRoom - **Description**: 命令行下的聊天室 --Python Socket实现 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2018-08-17 - **Last Updated**: 2022-04-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ChatRoom ### 项目介绍 一个在线聊天室,采用TCP连接,搭建异步非阻塞的服务端和客户端,允许多个人同时一起聊天,每个人发送的消息会传递给所有人,类似于 QQ 群的功能。 **** ### 技术栈 * Python + select + 多线程 ### 开发环境 * JetBrains Pycharm 2017 * Python 3.5.4 ### 说明 代码中的变量名不严谨地把套接字和描述符混为一谈,实际上我们的程序一直是对描述符进行操作,本文档中我会认真地表述出来。 server_select.py和sever_threadpool.py 分别用select函数监听描述符的变化和利用线程池两种方法实现的服务器。 客户端client.py使用多线程并行处理socket I/O ![image](image/client.gif "客户端收发情况")客户端收发情况 ![image](image/server.png "服务端提示信息")服务端提示信息 ### 设计思路 socket的基础操作这里不表 ![image](image/socket.png) myserver.py下的Server基类封装了服务器的基本功能,功能介绍添加在相应代码下。 **** server_select.py * [参考了主要参考中的第一个链接](#主要参考) 核心函数select.select 同时响应多个socket事件 ```python readable, writable, exceptional = select.select(inputs, outputs, inputs) ``` > 当用户进程调用了select,那么整个进程会被阻塞(block),同时“监听”所有select负责的描述符,当任何一个描述符 有数据到达时,或者某个 socket 可以写数据时,又或者是当某个 socket 发生错误,select就会返回。 select 方法的三个参数都是 list 类型,分别代表读事件、写事件、错误事件,同样方法返回值也是三个 list,包含的是哪些事件(读、写、异常)有了相应。 本例子中仅对读事件(readable)做了处理。 当响应的是监听描述符(listenfd),说明与新用户发生了连接,创建连接描述符(conn)与客户端套接字连接在一起,并把相应的连接描述符添加进监听列表(socket_list) 当响应的是连接描述符,判断是离线消息,还是用户正常发生的消息,执行相关操作,将消息"广播"(broadcast)到所用客户端。 **** sever_threadpool.py multiprocessing是Python的标准模块,它既可以用来编写多进程,也可以用来编写多线程。这里我们用这个模块维护了一个线程池,有多少客户端连入,我们就创造几个线程,且得益于线程之间的数据共享,这个程序中多线程比多进程性能要好些。如果池中的线程数已经达到规定最大值,那么该请求就会等待,直到池中有线程结束。 ``` 测试中发现程序在一段时间后所占内存持续变大,原因不明!``` 已修复:线程池任务调度上出错 **** client.py 创建两个线程,一个接收信息,一个发送信息。 ### 主要参考 [Python socket – chat server and client with code example](https://www.binarytides.com/code-chat-application-server-client-sockets-python/) [【Multiprocessing系列】Multiprocessing基础](https://thief.one/2016/11/23/Python-multiprocessing/) ### 总结 通过这个项目只是想了解socket编程,完成基本操作后,我也不想在使用体验上进行打磨,我是觉得用个UI把输入和输出独立出来会好很多。 通讯方面,了解基本原理和步骤,直接调用socket库的API即可。不过我在字节流和比特流之间的出过错,很简单的东西,但写到后面人晕了,在这种小错误上费了很多时间,后来我也想过对策,对输入做个判断啊,变量命名更加有意义,吸取一个教训。 这次客户端的实现用了两种方法,都是对通过对基类的继承,扩展各自的功能,稍微有点明白OOP思想了。 关于并行编程,认识还有很多不够,靠着网上的教程,勉强完成了相应的功能。