我希望使用带有非阻塞标志MSG_NONBLOCK的recv
系统调用。但是,使用此标志系统调用可能会在完整请求满足之前返回。
- 我可以添加MSG_WAITALL标志吗?它会是非阻塞的吗?
- 还是说我应该将阻塞的
recv
重写为带有非阻塞recv
的循环?
我希望使用带有非阻塞标志MSG_NONBLOCK的recv
系统调用。但是,使用此标志系统调用可能会在完整请求满足之前返回。
recv
重写为带有非阻塞recv
的循环?对于至少在Linux上的IPv4 TCP接收,如果指定了MSG_NONBLOCK(或文件描述符设置为非阻塞),则将忽略MSG_WAITALL。
来自Linux内核中net/ipv4/tcp.c中的tcp_recvmsg():
if (copied >= target && !sk->sk_backlog.tail)
break;
if (copied) {
if (sk->sk_err ||
sk->sk_state == TCP_CLOSE ||
(sk->sk_shutdown & RCV_SHUTDOWN) ||
!timeo ||
signal_pending(current))
break;
timeo
为零只是表示没有设置读取超时,对吗? - user207421我为同样的问题做了以下操作,但是我希望得到一些确认,证明这个方案可以正常工作...
ssize_t recv_allOrNothing(int socket_id, void *buffer, size_t buffer_len, bool block = false)
{
if(!block)
{
ssize_t bytes_received = recv(socket_id, buffer, buffer_len, MSG_DONTWAIT | MSG_PEEK);
if (bytes_received == -1)
return -1;
if ((size_t)bytes_received != buffer_len)
return 0;
}
return recv(socket_id, buffer, buffer_len, MSG_WAITALL);
}
编辑:
普通的recv()将返回调用时tcp缓冲区中请求字节数的任何内容。MSG_DONTWAIT只是避免了在套接字上没有准备好读取的数据时阻塞。MSG_WAITALL请求阻塞,直到可以读取请求的全部字节数。因此,您不会得到“全部或无”的行为。如果没有数据存在,则最多应该获得EAGAIN并阻塞,直到完整消息可用为止。
您可能能够使用MSG_PEEK或ioctl()与FIONREAD(如果系统支持)创建出您想要的有效行为,但我不知道您如何仅使用recv()标志来实现您的目标。