IO多路复用
select 多路复用技术
32系统只能1024个连接 64位 2048个
采用轮询机制,当并发大的时候,就会崩了
POLL只是突破了连接的限制
上代码:
from socket import *
import select
def main():
# 创建对象
tcp_server = socket(AF_INET, SOCK_STREAM)
# 绑定地址
tcp_server.bind(('', 8888))
# 将主动模式设置为被动模式
tcp_server.listen(5)
# 初始化一个列表
server_lists = [tcp_server] # 将初始socket对象添加至列表中
while True:
sockets, _, _ = select.select(server_lists, [], [])
for obj in sockets:
if obj == tcp_server:
# 创建新的连接
new_socket, client_info = obj.accept()
# 将新的new_socket对象添加至列表
server_lists.append(new_socket)
# 打印连接信息
print(f'来自{client_info} 连接成功!')
else:
# 接收数据
raw_data = obj.recv(1024)
# 注意: 这个地方不能使用死循环,否则会导致阻塞情况,同一时总能一个客户端通信,其他客户端将阻塞排队中,当前面断开是,后面的讲可以继续通信
if raw_data:
# 打印数据
print(f'接收到数据: {raw_data.decode("gb2312")}')
else:
# 内容为空 移出连接信息
server_lists.remove(obj)
obj.close()
if __name__ == '__main__':
main()
epoll 多路复用技术( 高并发 )
什么是epoll多路复用?
poll已实现无数连接 轮询
epoll 改成事件通知
只能在Linux上使用 不能在window使用
上代码:
from socket import *
import select
def main():
# 创建对象
tcp_socket = socket(AF_INET, SOCK_STREAM)
# 绑定地址
tcp_socket.bind(('', 8888))
# 将主动模式设置为被动模式
tcp_socket.listen(5)
# 创建epoll
epoll = select.epoll()
# 把被动套接字添加至监听读状态
epoll.register(tcp_socket.fileno(), select.EPOLLIN)
# 声明一个字典 用来存新创建套接字
new_sockets = {}
client_infos = {}
while True:
epoll_list = epoll.poll()
for fd, _ in epoll_list:
if fd == tcp_socket.fileno():
# 创建新的连接
new_socket, client_info = tcp_socket.accept()
# 把新对象添加至监听
epoll.register(new_socket.fileno(), select.EPOLLIN)
# 添加至字典
new_sockets[new_socket.fileno()] = new_socket
client_infos[client_info] = client_info
print(f'来自{client_info} 连接成功!')
else:
# 接收数据
raw_data = new_sockets[fd].recv(1024)
# 判断是否有数据
if raw_data:
print(f'来自{client_info}的信息: {raw_data.decode("gb2312")}')
else:
print('客户端已断开!')
# 客户端已关闭
new_sockets[fd].close()
# 注销监听队列
epoll.unregister(fd)
# 移除字典
del new_sockets[fd]
del client_infos
if __name__ == '__main__':
main()
专业名词
- IO阻塞:Input output 输入输出 一写有一个缓存的东西 一定是读写操作 去缓存区取东西,如果没有就等待
- IO非阻塞:去缓存区取东西,不管有没有,必需得取,取到就正常,否则就异常
- 轮询:每个人都要问一遍,非常耗时
- 事件通知机制:epoll 采用这个机制