MST

星途 面试题库

面试题:Python socket模块中fileno属性在复杂网络场景中的应用

在Python socket编程里,fileno属性返回socket对象的文件描述符。假设你正在开发一个需要与多个socket进行交互且使用多路复用(如selectors模块)的复杂网络应用,如何利用fileno属性实现高效的多路复用,并解释这样做的原理。
33.1万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试
  1. 利用fileno属性实现高效多路复用的方法

    • 以下是使用selectors模块结合fileno属性的示例代码:
    import selectors
    import socket
    
    # 创建默认的选择器对象
    sel = selectors.DefaultSelector()
    
    def accept(sock, mask):
        conn, addr = sock.accept()  # 接受新连接
        print('accepted', conn, 'from', addr)
        conn.setblocking(False)
        # 注册新连接的socket对象,监听读事件
        sel.register(conn, selectors.EVENT_READ, read)
    
    def read(conn, mask):
        data = conn.recv(1024)  # 读取数据
        if data:
            print('echoing', repr(data), 'to', conn)
            conn.send(data)  # 回显数据
        else:
            print('closing', conn)
            sel.unregister(conn)
            conn.close()
    
    # 创建服务器socket
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(('localhost', 12345))
    sock.listen(100)
    sock.setblocking(False)
    # 注册服务器socket,监听读事件,回调函数为accept
    sel.register(sock, selectors.EVENT_READ, accept)
    
    try:
        while True:
            events = sel.select()  # 阻塞等待事件发生
            for key, mask in events:
                callback = key.data
                callback(key.fileobj, mask)
    except KeyboardInterrupt:
        print('caught keyboard interrupt, exiting')
    finally:
        sel.close()
    
    • 在上述代码中,sel.register(sock, selectors.EVENT_READ, accept) 这一步用到了fileno属性。selectors模块的register方法实际上是通过调用socket对象的fileno方法获取文件描述符,然后将其加入到多路复用的监控集合中。例如对于服务器socksel.register(sock, selectors.EVENT_READ, accept)selectors模块内部会调用sock.fileno()获取其文件描述符,以便在select调用时能对该socket进行监控。
  2. 原理

    • 多路复用概念:多路复用技术允许应用程序在单线程内同时监控多个I/O事件,避免了为每个socket创建一个单独线程或进程所带来的资源开销。
    • fileno属性的作用:在操作系统层面,I/O操作是基于文件描述符的。在Python中,socket对象通过fileno属性提供了与操作系统交互的接口,返回一个整数类型的文件描述符。selectors模块(其底层依赖操作系统的selectpollepoll等系统调用,具体取决于操作系统)通过这些文件描述符来监控socket的I/O状态。当调用sel.select()时,操作系统会检查这些文件描述符对应的socket是否有可读、可写或错误等事件发生。如果有事件发生,select调用会返回对应的文件描述符集合(在Python中通过events变量获取),应用程序就可以对这些发生事件的socket进行相应处理。这样,通过fileno属性将Python的socket对象与操作系统的I/O多路复用机制联系起来,实现了高效的多路复用。