osg*_*sgx 9 sockets linux network-programming nonblocking
我想使用recv带有非阻塞标志MSG_NONBLOCK的系统调用.但是使用此标志,syscall可以在满足完整请求之前返回.所以,
至少对于 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;
如果指定了 MSG_DONTWAIT,则此转换中的目标设置为请求的大小;如果未指定,则设置为某个较小的值(至少 1)。如果出现以下情况,该函数将完成:
对我来说,这似乎可能是 Linux 中的一个错误,但无论如何它都不会按照你想要的方式工作。看起来 dec-vt100 的解决方案可以,但是如果您尝试在多个进程或线程中从同一个套接字接收数据,则会出现竞争条件。
也就是说,在您的线程执行查看之后,另一个线程/进程可能会发生另一个 recv() 调用,从而导致您的线程在第二个 recv() 上阻塞。
编辑:
普通的recv()将返回调用时tcp缓冲区中的任何内容,最多可达请求的字节数。如果套接字上根本没有数据可供读取,MSG_DONTWAIT 只是避免阻塞。MSG_WAITALL 请求阻塞,直到可以读取请求的全部字节数。所以你不会得到“全有或全无”的行为。如果没有数据存在,您最多应该得到 EAGAIN,否则会阻塞直到完整消息可用。
您也许可以使用 FIONREAD(如果您的系统支持它)从 MSG_PEEK 或 ioctl() 中设计一些东西,使其有效地表现得像您想要的那样,但我不知道如何仅使用 recv() 标志来实现您的目标。
| 归档时间: | 
 | 
| 查看次数: | 17706 次 | 
| 最近记录: |