You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python Asyncio Streams API中设置Socket选项(如SO_KEEPALIVE)

使用asyncio Streams API设置Socket保活选项

你完全可以设置这类Socket选项,核心是在asyncio.open_connection接管Socket前配置参数,或后续通过流对象获取底层Socket修改,以下是两种可靠实现方式:

方法一:手动创建Socket并配置后传入open_connection

先手动实例化Socket,设置好所有需要的选项,再通过sock参数传给asyncio.open_connection,配置会被完整保留:

import asyncio
import socket

async def main():
    # 手动创建Socket并设置保活选项
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
    # 按需设置TCP层面保活参数(不同系统有差异)
    if hasattr(socket, 'TCP_KEEPIDLE'):
        sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 30)
        sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 10)
        sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 3)
    
    # 将配置好的Socket传给open_connection
    reader, writer = await asyncio.open_connection(
        host='example.com',
        port=80,
        sock=sock
    )
    
    # 正常使用流对象
    writer.write(b'GET / HTTP/1.1\r\nHost: example.com\r\n\r\n')
    await writer.drain()
    
    data = await reader.read(1024)
    print(f"Received: {data.decode()}")
    
    writer.close()
    await writer.wait_closed()

asyncio.run(main())

方法二:通过流对象的底层Socket修改

如果已通过open_connection创建连接,可从writer对象中获取底层Socket设置选项(优先推荐方法一,此方式需确保接管后操作有效,大部分场景下没问题):

import asyncio
import socket

async def main():
    reader, writer = await asyncio.open_connection('example.com', 80)
    
    # 获取底层Socket并设置保活
    sock = writer.transport.get_extra_info('socket')
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
    # 按需设置TCP保活参数
    if hasattr(socket, 'TCP_KEEPIDLE'):
        sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 30)
        sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 10)
        sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 3)
    
    # 正常使用流对象
    writer.write(b'GET / HTTP/1.1\r\nHost: example.com\r\n\r\n')
    await writer.drain()
    
    data = await reader.read(1024)
    print(f"Received: {data.decode()}")
    
    writer.close()
    await writer.wait_closed()

asyncio.run(main())

关键注意点

  • Socket的选项设置持久生效,asyncio接管Socket后只会负责后续IO操作和关闭,不会重置你提前设置的参数,文档中“转移所有权”仅指操作权移交,不涉及配置修改。
  • TCP层面的保活参数(如TCP_KEEPIDLE)是平台相关的,Windows与Linux参数名可能不同,需用hasattr做兼容性判断。
  • 若使用asyncio.start_server创建服务端流,同样可通过transport.get_extra_info('socket')获取Socket设置保活选项。

内容的提问来源于stack exchange,提问作者rustyocean

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 10:55:20