Zumindest für IPv4-TCP-Empfang unter Linux wird MSG_WAITALL ignoriert, wenn MSG_NONBLOCK angegeben ist (oder der Dateideskriptor auf non-blocking gesetzt ist).
Aus tcp_recvmsg() in net/ipv4/tcp.c im Linux-Kernel:
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;
target wird in diesem Cast auf die angeforderte Größe gesetzt, wenn MSG_DONTWAIT angegeben ist, oder auf einen kleineren Wert (mindestens 1), wenn nicht. Die Funktion wird beendet, wenn:
- Es wurden genügend Bytes kopiert
- Es liegt ein Socket-Fehler vor
- Die Steckdose wurde geschlossen oder heruntergefahren
- timeo ist 0 (Socket ist auf nicht-blockierend eingestellt)
- Es steht ein Signal für den Prozess an
Mir scheint, dass es sich um einen Fehler in Linux handelt, aber so oder so wird es nicht so funktionieren, wie Sie es wünschen. Es sieht so aus, als würde die Lösung von dec-vt100 funktionieren, aber es gibt eine Race Condition, wenn Sie versuchen, von demselben Socket in mehr als einem Prozess oder Thread zu empfangen.
Das heißt, ein weiterer recv()-Aufruf durch einen anderen Thread/Prozess könnte erfolgen, nachdem Ihr Thread einen Peek durchgeführt hat, wodurch Ihr Thread beim zweiten recv() blockiert wird.