Python 提供了两个级别访问的网络服务。:
- 低级别的网络服务支持基本的 socket,,可以访问底层操作系统Socket接口的方法。
- 高级别的网络服务模块 socketserver, 可以简化网络服务器的开发。
socket
查看socket类的帮助如下
import socket # 导入socket模块
>>> help(socket.socket)
重点关注初始化函数:
__init__(self, family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_STREAM: 1>, proto=0, fileno=None)
- family:网络协议簇,默认值为AF_INET
- type:套接字的类型,根据是面向连接的还是非连接分为
SOCK_STREAM
或SOCK_DGRAM
- proto:套接字协议,一般默认为0,表示
- fileno:套接字的int型的文件描述符
下面实现一个TCP聊天室和一个UDP聊天室
TCP聊天室
概要设计
获取多个连接的处理
开启accept线程,执行accept操作开始阻塞,有客户端连接时,再开启一个线程recv进行数据接收的处理。然后accept线程继续阻塞,等待后续客户端的连接。
阻塞的处理
服务端处理客户端的连接时,有两处存在阻塞,分别是:
- 获取连接时,socket.accept()会阻塞
- 每一个建立成功的连接在获取数据时,socket.recv(1024)
因此这两处都需要开启线程单独处理,否则会阻塞主线程。
客户端主动断开的处理
客户端主动断开时,如果不通知服务端,那么服务端上保存的客户端连接不会被清理,这是不合理的。因此客户端主动断开时,我们在应用层约定,客户端推出前需要发送/quit
指令到服务端上,然后有服务端关闭socket。
TCP聊天室-server
聊天室的server端主要是监听端口,处理来自client端的连接,并且分发数据到所有的client端
代码
import socket
import threading
class TcpChatServer:
def __init__(self, ip='192.168.110.13', port=9001):
self.ip = ip
self.port = port
self.clients = {}
self.sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
self.event = threading.Event()
def recv(self, so, ip ,port