如何在pysctp库中使用sctpsocket_udp class
How to use sctpsocket_udp class in pysctp library
我正在尝试使用 pysctp 库设置一个基本的 SCTP client/server 示例。我想使用 sctp.sctpsocket_udp
class 因为根据相关文档字符串:
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[=13=]77[=13=]`2", [8]) = 0
1034 getsockopt(3, 0x84 /* SOL_??? */, 11, "[=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=]", [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)
我试图重新启动我的计算机以防某些资源挂起,但这没有任何帮助。
解决了这个问题。
在幕后,调用 socket.settimeout(1)
或类似地调用 socket.setblocking(False)
我也尝试过,导致底层套接字设置为非阻塞。这成为一个问题的原因是,虽然大多数套接字操作(例如,只是您在 sctp.sctpsocket_udp
对象上调用的普通 socket.recvmsg
被委托给 python socket
对象,sctp_*
调用不会,它们是通过 pysctp 的 _sctp.c
C 扩展组件处理的。这意味着,当你做一些导致底层套接字非阻塞的事情时,比如 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
因此表示此时没有可用数据,所以请睡眠或其他,然后重试。
我正在尝试使用 pysctp 库设置一个基本的 SCTP client/server 示例。我想使用 sctp.sctpsocket_udp
class 因为根据相关文档字符串:
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[=13=]77[=13=]`2", [8]) = 0
1034 getsockopt(3, 0x84 /* SOL_??? */, 11, "[=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=][=13=]", [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)
我试图重新启动我的计算机以防某些资源挂起,但这没有任何帮助。
解决了这个问题。
在幕后,调用 socket.settimeout(1)
或类似地调用 socket.setblocking(False)
我也尝试过,导致底层套接字设置为非阻塞。这成为一个问题的原因是,虽然大多数套接字操作(例如,只是您在 sctp.sctpsocket_udp
对象上调用的普通 socket.recvmsg
被委托给 python socket
对象,sctp_*
调用不会,它们是通过 pysctp 的 _sctp.c
C 扩展组件处理的。这意味着,当你做一些导致底层套接字非阻塞的事情时,比如 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
因此表示此时没有可用数据,所以请睡眠或其他,然后重试。