MST

星途 面试题库

面试题:Python 网络编程中的并发处理

在Python的服务器端网络编程中,假设要处理大量并发的客户端连接,使用`socket`模块结合`asyncio`库来实现一个能够高效处理并发请求的服务器。每个请求要求服务器读取一个本地文本文件,并将文件内容返回给客户端。请阐述实现步骤并给出关键代码。
41.3万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试

实现步骤

  1. 导入必要的库:导入asynciosocket模块。
  2. 创建服务器套接字:使用socket模块创建一个TCP套接字,并绑定到指定的地址和端口,然后开始监听连接。
  3. 定义处理客户端请求的协程:在协程中,接受客户端连接,读取本地文本文件内容,将内容发送给客户端,最后关闭连接。
  4. 使用asyncio运行服务器:通过asyncio的事件循环来启动服务器,使其能够处理多个并发连接。

关键代码

import asyncio
import socket


async def handle_connection(reader, writer):
    try:
        with open('local_file.txt', 'r') as file:
            content = file.read()
        writer.write(content.encode())
        await writer.drain()
    except FileNotFoundError:
        writer.write(b'File not found')
        await writer.drain()
    finally:
        writer.close()


async def start_server():
    server = await asyncio.start_server(handle_connection, '127.0.0.1', 8888)
    async with server:
        await server.serve_forever()


if __name__ == "__main__":
    asyncio.run(start_server())

在上述代码中:

  • handle_connection协程处理每个客户端连接,负责读取文件内容并发送给客户端。
  • start_server协程创建并启动服务器,将handle_connection协程关联到服务器,使其处理客户端连接。
  • asyncio.run(start_server())启动事件循环并运行服务器。注意:这里使用asyncio.start_server替代了socket模块手动处理连接部分,asyncio.start_server内部已经结合了socket底层操作并实现异步化。如果非要结合socket模块,可以参考以下代码:
import asyncio
import socket


async def handle_connection(client_socket):
    try:
        with open('local_file.txt', 'r') as file:
            content = file.read()
        client_socket.sendall(content.encode())
    except FileNotFoundError:
        client_socket.sendall(b'File not found')
    finally:
        client_socket.close()


async def start_server():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server_socket.bind(('127.0.0.1', 8888))
    server_socket.listen()
    server_socket.setblocking(False)
    while True:
        client_socket, addr = await asyncio.get_running_loop().sock_accept(server_socket)
        asyncio.create_task(handle_connection(client_socket))


if __name__ == "__main__":
    asyncio.run(start_server())

此代码中,手动使用socket模块创建套接字,设置为非阻塞模式,通过asyncio.get_running_loop().sock_accept接受客户端连接,并为每个连接创建一个任务来处理。