socket多路复用的技术

socket多路复用的技术

就像上一篇的思想一样,socket多路复用就是实现在一个进程中抗并发.核心的思维就是使用中间缓存

socket抗并发的原理

在系统内核中存在一个监控的系统,当服务器启动的时候,server对象就会在程序中创建,socket已经内置好了一个空间专门用来监控的.如果有客户端进行服务器连接,那么server对象就会发生变化,socket内核就会监控这种变化,一旦发现某个被监控对象发生状态变化,则直接将这个对象拿出来,进行执行对应的程序

如果是客户端连接,那么server就应该创建新对象,new_server,创建的这个新对象依然需要扔到socket中进行监控,因为这里只是连接,如果客户端给服务器发送数据,这也会导致new_server发生状态改变,因此需要继续监控

如果监控到发生状态变化的不是server对象,而是new_server对象,这就表明客户端已经发送了数据给服务端,那么连接的对象new_server就应该去接收数据

我们功能做简单点,当接收到数据后打印数据,然后再关闭连接,关闭连接后如果不把监控区的对象进行删除,那么始终在内核中还是要对其进行监控,就算以后再也不发生状态变化,其也会占用内存,非常浪费资源,所以需要进行删除

总体思维还是上一篇的使用中间区域进行暂时存储创建的连接对象,然后再进行遍历,将对象进行挨个执行,只是socket使用的是阻塞模式,这就不会导致需要死循环来实现,cpu压力就不大,然后socket内核能够实现对这个监控区域的监控,一旦有对象发生状态变化就把它取出来,自动解除阻塞,如果同时间有多个对象状态发生变化,则全部取出来以列表的形式返回

下面是代码实现

from socket import *
import select


def main():
    # 创建对象
    server = socket(AF_INET, SOCK_STREAM)
    # 配置断开释放端口
    server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
    # 挂起服务器
    server.bind(('', 8888))
    # 设置成监听模式
    server.listen()
    # 把server对象扔到列表中取
    save_list = [server]
    while True:
        # 使用select进行监听save_list中的对象是否发生改变
        sockets, _, _ = select.select(save_list, [], [])
        # 监听返回的列表中就是我们需要的对象,所以这里了进行遍历
        for new_obj in sockets:
            # 如果是客户端连接动作,则一定会有一个server发生改变,则上面select就会解除阻塞
            if new_obj == server:
                # 如果改变的对象是server则表明这是一个客户端连接动作,那么需要创建新对象
                new_server, client_info = new_obj.accept()
                print(f'用户{client_info}已经连接')
                # 这个时候就把新对象保存到save_list中
                save_list.append(new_server)
            else:
                # 这里除了第一个server是对象之外其他的元素都是元组,只要是元组就一定是server创建的连接
                # 获取数据
                data = new_obj.recv(1024)
                # 打印数据
                print(f'收到用户的数据{data}')
                # 接收完成之后关闭连接
                new_obj.close()
                # 从save_list中剔除
                save_list.remove(new_obj)


if __name__ == '__main__':
    main()

监控效率不高的原因

原生的socket抗并发实际上不是很理想

首先是对状态改变的判断这个动作,其执行的是一种

轮询

的方式,所谓轮询,可以简单的形象理解就是挨个问,就像你进一个教室,想找出名字叫吊炸天的人,你又不认知班上任何一个人,那么你就从第一排开始一个一个的去问:‘你是吊炸天么’.

其次是其本身的抗并发能力有限,如果是32位的系统就是1024并发数,如果是64位的系统就是2048并发数

后面有poll这种技术,实质的轮询问题没有解决,只是把并发数改到了没有限制

那么socket和poll都是存在轮询这个浪费时间的过程

没办法,下一篇介绍epoll技术能够解决这个问题

猜你喜欢

转载自blog.csdn.net/weixin_43959953/article/details/85008441