MST

星途 面试题库

面试题:网络编程之Python Socket高级难度题

假设你正在使用Python的Socket进行高并发网络编程,使用多线程或异步I/O实现一个简单的聊天服务器,要求处理多个客户端连接,并且能够正确处理消息的接收和发送,同时考虑到异常处理和资源释放,请详细阐述实现思路并给出核心代码片段。
39.5万 热度难度
后端开发网络编程

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 使用异步I/O:选择asyncio库来实现异步I/O,以处理高并发连接。asyncio提供了异步编程的基础设施,允许在单线程内高效处理多个I/O操作。
  2. 处理客户端连接:使用asyncio.start_server创建一个服务器,该服务器会监听指定的地址和端口,每当有新的客户端连接时,创建一个新的任务来处理该客户端的通信。
  3. 消息接收和发送:在处理客户端连接的任务中,使用异步的readerwriter对象来接收和发送消息。reader用于读取客户端发送的数据,writer用于向客户端发送数据。
  4. 异常处理:在处理客户端连接的任务中,使用try - except块捕获可能出现的异常,如连接断开、数据读取错误等,并进行相应的处理,例如关闭连接、记录日志等。
  5. 资源释放:当客户端连接结束时,确保正确关闭writer对象以释放资源,避免资源泄漏。

核心代码片段

import asyncio


async def handle_connection(reader, writer):
    try:
        while True:
            data = await reader.read(1024)
            if not data:
                break
            message = data.decode('utf - 8')
            print(f"Received: {message}")
            response = f"Message received: {message}"
            writer.write(response.encode('utf - 8'))
            await writer.drain()
    except Exception as e:
        print(f"Error: {e}")
    finally:
        writer.close()
        await writer.wait_closed()


async def main():
    server = await asyncio.start_server(handle_connection, '127.0.0.1', 8888)
    addr = server.sockets[0].getsockname()
    print(f'Serving on {addr}')
    async with server:
        await server.serve_forever()


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

代码解释

  1. handle_connection函数
    • 这是处理每个客户端连接的异步函数。
    • 使用while True循环不断读取客户端发送的数据,await reader.read(1024)表示异步等待最多读取1024字节的数据。
    • 如果没有读取到数据(if not data:),说明客户端关闭了连接,跳出循环。
    • 接收到数据后,将其解码为字符串并打印,然后构造响应消息并发送回客户端,await writer.drain()确保数据被真正发送出去。
    • 使用try - except捕获可能出现的异常并打印错误信息。
    • finally块中,关闭writer并等待其关闭,以确保资源释放。
  2. main函数
    • 使用asyncio.start_server创建一个服务器,传入处理连接的函数handle_connection以及监听的地址和端口。
    • 获取服务器套接字的地址并打印。
    • 使用async with server确保服务器资源的正确管理,await server.serve_forever()使服务器持续运行,等待客户端连接。
  3. if __name__ == "__main__"
    • 使用asyncio.run(main())来运行异步主函数,启动聊天服务器。