当我从 NETLINK_ROUTE 套接字创建尝试
socket.recv()
时,如果我没有接收所有可用数据,则似乎未接收的数据会丢失。
例如:
>>> import socket
>>> sock = socket.socket(socket.AF_NETLINK, socket.SOCK_DGRAM, socket.NETLINK_ROUTE)
>>> sock.bind((0,0))
>>> sock.send('\24\0\0\0\22\0\1\3\23\0364O\0\0\0\0\21\0\0\0') # struct nlmsghdr
20
>>> sock.recv(10000)
'\xe4\x03\x00\x00 ... ' (+3000 more bytes)
如果我
sock.recv(100)
,它将返回 100 个字节,但 +2900 个其他字节消失了。 执行另一个 sock.recv()
将返回下一个 nlmsghdr (如果是多部分消息)或阻止等待数据。
我可以
sock.recv(X, socket.MSG_PEEK)
读取X字节而不丢失数据;但这样做时,读取的数据当然不会从接收缓冲区中弹出。
我认为任何未读取的数据都会保留在缓冲区中直到被读取。我做错了什么? 我不想只是“猜测”有多少数据可用......
这就是数据报(SOCK_DGRAM 套接字)的工作方式——保留消息边界,当您不读取整个数据包时,其余部分将被丢弃(SOCK_STREAM 套接字,即 TCP 提供字节流服务,您可以在其中读取任意数量的字节)一次,其余的将保留在套接字缓冲区中)。
Netlink 提供数据报服务,您可以使用 SOCK_DGRAM 或 SOCK_RAW 套接字。
问题是什么? AFAIK netlink 对消息大小有上限,您应该仅使用它来接收消息。
循环读取(并处理)所有数据报,直到在一段时间内没有收到任何数据报。 可以使用非阻塞套接字和 select.select 并设置超时来实现此目的。