为了巩固网络编程知识点,写了一个不带界面的多人聊天程序
结构

Setting
setting.py 包含初始化套接字的参数和方法
1 | import socket |
Server
服务器运行流程:
- 服务器创建套接字s_serv,该套接字用于接收用户连接。将s_serv放进rlst侦听
- select 函数侦听rlst,如果侦听到s_serv可读,说明有新用户发起了连接。s_serv.accpet()接受用户连接,产生两个返回值,分别是连接句柄和对端的地址元组;
- 将连接句柄放入rlst,这样select也会侦听这个与客户端的连接句柄,如果客户端通过这个连接发送消息,会被select侦听到;
- select有三个返回值,三个值分别是可读列表、可写列表和异常列表,它会将侦听符合状态的socket分别放进这三个列表中;
- 通过for循环可以遍历返回的列表;
- 这样,服务端便实现了接收新用户连接和接收已连接用户消息的功能;
- 收到消息后,遍历rlst ,得到所有与客户端的连接句柄,用连接句柄向每一个客户端发送消息,这样就实现了接受用户消息并将消息发送给所有在线用户的功能。
1 | #server |
Client
客户端运行流程:
- 客户端创建s_cli 和p_serv两个套接字,前者用于与服务器通信,后者用于接收键盘输入
- 创建子线程,令子线程运行select ,侦听s_cli 和 p_serv 的状态;
- 主线程等待用户输入;
- 主线程收到用户输入后,创建p_cli,用p_cli带着用户输入的数据连接p_serv ,p_serv收到p_cli 的连接,变成可读状态,被select装进列表返回;
- for循环遍历可读列表,如果元素为p_serv,p_serv.accept()得到连接,再通过连接取出其中的数据,最后通过s_cli.send()将数据发送给服务端;
- 如果刻度列表中有s_cli,则客户端收到了从服务端发来的数据,通过s_cli.recv()取出
- 这样就实现了侦听键盘输入并发送和接收服务器的工作。
- 实际上,p_serv不是必要的,如果想要简化代码的话,可以在接收键盘输入后直接通过s_cli.send(data)把数据发送给服务端。但个人感觉这样在程序设计上不太合理,因为数据传输和用户输入是两个行为,应该做区分。
1 | #client.py |
