在pysctp库中使用sctpsocket_udp类的方法

2024-09-28 21:30:38 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试使用pysctp库设置一个基本的SCTP客户机/服务器示例。我想使用sctp.sctpsocket_udp类,因为根据相关的文档字符串:

A UDP-style SCTP socket can hold several associations via a single socket.

…这就是我需要的功能。到目前为止,我掌握的情况如下:

server_sock = sctp.sctpsocket_udp(socket.AF_INET)
server_sock.bind((str(ip_address), port))
server_sock.listen(16)
server_sock.settimeout(1)

while not done:
    time.sleep(3)
    fromaddr, flags, msg, notif = server_sock.sctp_recv(3*1024*1024)

为了简洁起见,我当然省略了进口之类的东西。底线是,当这个被执行时,我会得到以下错误:

BlockingIOError: [Errno 11] Resource temporarily unavailable

相应的堆栈跟踪表明问题出现在对_sctp.sctp_recv_msg(...)的底层调用上

strace的输出显示如下:

1032 socket(PF_INET, SOCK_SEQPACKET|SOCK_CLOEXEC, IPPROTO_SCTP) = 3
1033 getsockopt(3, 0x84 /* SOL_??? */, 2, "\n\0\377\377\10\0`\352", [8]) = 0
1034 getsockopt(3, 0x84 /* SOL_??? */, 11, "\0\0\0\0\0\0\0\0\0\0", [10]) = 0
1035 bind(3, {sa_family=AF_INET, sin_port=htons(9000), in_addr=inet_addr("127.0.0.1")}, 16) = 0
1036 listen(3, 16)                           = 0
1037 ioctl(3, FIONBIO, [1])                  = 0
1038 mmap(NULL, 3149824, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd621646000
1039 recvmsg(3, 0x7ffe1a59ba40, 0)           = -1 EAGAIN (Resource temporarily unavailable)

我试图重新启动我的电脑,以防有一些资源挂起打开,但这没有帮助。你知道吗


Tags: serverbindportmsgsocketlistenresourcesctp
1条回答
网友
1楼 · 发布于 2024-09-28 21:30:38

找到了这个问题。你知道吗

在引擎盖下,调用socket.settimeout(1)或类似地调用socket.setblocking(False)(我也尝试过)会导致底层套接字设置为非阻塞。这成为一个问题的原因是,虽然大多数套接字操作(例如,仅对sctp.sctpsocket_udp对象调用的普通socket.recvmsg)被委托给python socket对象,但sctp_*调用没有,它们是通过pysctp的_sctp.cC扩展组件处理的。这意味着,当您执行一些导致底层套接字非阻塞的操作时,例如socket.settimeout(1),然后使用其中一个sctp_*函数,而不是超时然后得到一个socket.timeout异常,您最终会进入底层C扩展的这一部分:

size = sctp_recvmsg(...)
if(size < 0){
    free(msg);
    PyErr_SetFromErrno(PyExc_IOError);
    return ret;
}

因此,获取上面引用的BlockingIOError。解决方案是使用非阻塞模式,而不是麻烦超时,然后捕获BlockingIOError而不是socket.timeout,只需检查异常的errno属性,以确保它是EAGAIN,从而指示此时没有可用的数据,所以请睡眠或其他操作,然后重试。你知道吗

相关问题 更多 >