it-swarm.com.de

Linux: Gibt es einen Read oder Recv von Socket mit Timeout?

Wie kann ich versuchen, Daten aus Socket mit Timeout zu lesen? Ich weiß, wählt, pselect, poll, hat ein Timeout-Feld, aber bei Verwendung von "tcp fast-path" im TCP Reno Stack deaktiviert.

Die einzige Idee, die ich habe, ist recv (fd, ..., MSG_DONTWAIT) in einer Schleife zu verwenden

86
osgx

Sie können die Funktion setsockopt verwenden, um ein Zeitlimit für Empfangsvorgänge festzulegen:

SO_RCVTIMEO

Legt den Timeout-Wert fest, der .__ angibt. die maximale Zeitdauer einer Eingabe Funktion wartet, bis sie abgeschlossen ist. Es akzeptiert eine zeitliche Struktur mit der Anzahl Sekunden und Mikrosekunden Festlegen des Grenzwerts für die Dauer von Warten Sie auf eine Eingabeoperation an Komplett. Wenn eine Empfangsoperation für so viel Zeit ohne .__ gesperrt. zusätzliche Daten erhalten, soll es Rückkehr mit einer Teilzählung oder errno auf [EAGAIN] oder [EWOULDBLOCK] setzen, wenn nein Daten werden empfangen. Der Standardwert für diese Option ist Null, was anzeigt, dass eine Empfangsbetrieb darf nicht ausfallen . Diese Option nimmt eine zeitliche Struktur an . Beachten Sie, dass nicht alle Implementierungen Erlaube diese Option zu setzen.

// LINUX
struct timeval tv;
tv.tv_sec = timeout_in_seconds;
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);

// WINDOWS
DWORD timeout = timeout_in_seconds * 1000;
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof timeout);

// MAC OS X (identical to Linux)
struct timeval tv;
tv.tv_sec = timeout_in_seconds;
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);

Berichten zufolge unter Windows sollte dies vor dem Aufruf von bind erfolgen. Ich habe durch Experiment verifiziert, dass dies vor oder nach bind unter Linux und OS X möglich ist.

162

Hier ist ein einfacher Code, um der recv-Funktion mithilfe der Umfrage in C Timeout hinzuzufügen:

struct pollfd fd;
int ret;

fd.fd = mySocket; // your socket handler 
fd.events = POLLIN;
ret = poll(&fd, 1, 1000); // 1 second for timeout
switch (ret) {
    case -1:
        // Error
        break;
    case 0:
        // Timeout 
        break;
    default:
        recv(mySocket,buf,sizeof(buf), 0); // get your data
        break;
}
17

Installieren Sie einen Handler für SIGALRM und verwenden Sie dann alarm() oder ualarm(), bevor Sie eine regelmäßige Blockierung recv() durchführen. Wenn der Alarm ausgelöst wird, gibt recv() einen Fehler zurück, wobei errno auf EINTR gesetzt ist.

0
caf

// funktioniert auch nach dem Bindevorgang für WINDOWS

DWORD timeout = timeout_in_seconds * 1000;
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof timeout);
0
cahit beyaz