Linux: Gibt es ein Lesen oder Empfangen vom Socket mit Timeout?

Lesezeit: 4 Minuten

Benutzeravatar von osgx
osgx

Wie kann ich versuchen, Daten vom Socket mit Timeout zu lesen? Ich weiß, select, pselect, poll, hat ein Timeout-Feld, aber die Verwendung von ihnen deaktiviert “tcp fast-path” im TCP-Reno-Stack.

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

  • Es besteht auch die Möglichkeit, Threads zu verwenden :), aber Thread-Signale werden immer noch benötigt

    – osgx

    4. Juni 2010 um 13:36 Uhr

Benutzeravatar von Robert S. Barnes
Robert S. Barnes

Du kannst den … benutzen setsockelopt Funktion zum Festlegen eines Timeouts für Empfangsvorgänge:

SO_RCVTIMEO

Legt den Zeitüberschreitungswert fest, der die maximale Zeitspanne angibt, die eine Eingabefunktion wartet, bis sie abgeschlossen ist. Es akzeptiert eine timeval-Struktur mit der Anzahl von Sekunden und Mikrosekunden, die das Limit angeben, wie lange auf den Abschluss einer Eingabeoperation gewartet werden soll. Wenn eine Empfangsoperation für diese lange Zeit blockiert wurde, ohne zusätzliche Daten zu empfangen, soll sie mit einer Teilzählung oder einer gesetzten Fehlernummer zurückkehren [EAGAIN] oder [EWOULDBLOCK] wenn keine Daten empfangen werden. Der Standardwert für diese Option ist Null, was angibt, dass eine Empfangsoperation kein Timeout haben soll. Diese Option nimmt eine Zeitstruktur an. Beachten Sie, dass nicht alle Implementierungen das Setzen dieser Option zulassen.

// 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 sollte dies unter Windows vor dem Anruf erfolgen bind. Ich habe durch Experimente verifiziert, dass es entweder vorher oder nachher gemacht werden kann bind unter Linux und OS X.

  • Diese Antwort hat mir den Arsch gerettet. Ich steckte fest und implementierte diesen verschlungenen “ausgewählten” Mist, ohne Erfolg. Dies funktionierte sofort, so viel einfacher.

    – MiloDC

    16. November 2017 um 21:06 Uhr

  • Deshalb funktioniert das Timeout unter Windows nicht, weil ich den Code für Linux verwende. Vielen Dank. Wenn Windows nicht verwendet wird struct timeval tv; bedeutet das dann, dass select() auch nicht funktioniert? Ich habe versucht, meinen select () -Code auf Windows zu portieren, und es wird sofort eine Zeitüberschreitung angezeigt. Es sieht so aus, als würde es den Wert ignorieren, den ich bei timeval festlege.

    – kuchi

    10. Dezember 2017 um 19:34 Uhr

  • Ich setze den Timeout-Wert auf 5 Sekunden. Warum dauert es immer 5 Sekunden für jeden Lesezyklus, egal ob Daten eingehen oder nicht?

    – Hann

    26. Februar 2018 um 12:57 Uhr

  • Dies funktioniert auch unter Windows, sogar nach dem Bindevorgang. auf windows 10 probiert

    – cahit beyaz

    4. April 2018 um 6:07 Uhr

  • @ user463035818 Diese Antwort behauptet, dass dies nicht der Fall sein sollte.

    – Tomamis

    14. April 2018 um 15:08 Uhr

Benutzeravatar von Abdessamad Doughri
Abdessamad Doughri

Hier ist ein einfacher Code, um eine Auszeit zu Ihrer hinzuzufügen recv Funktion verwenden poll in C:

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;
}

  • Dies würde nicht genau wie erwartet funktionieren. poll wartet auf den Empfang von mindestens einem Byte oder Timeout, während beim Aufrufen der recv Funktion, auf die gewartet wird sizeof(buf) Bytes, was dazu führt, dass es erneut blockiert, wenn diese Zählung noch nicht eingetroffen ist, diesmal jedoch ohne Timeout.

    – LoPiTaL

    23. Juni 2020 um 7:59 Uhr

  • Betrachtet man <man7.org/linux/man-pages/man2/recv.2.html> und <docs.microsoft.com/en-us/windows/win32/api/winsock/…>, recv sollte jede verfügbare Datenmenge bis zu zurückgeben sizeof(buf) Byte. Diese Lösung sollte also in Ordnung sein.

    – GILGAMESCH

    1. Januar 2021 um 23:11 Uhr

Benutzeravatar von cahit beyaz
cahit beyaz

// funktioniert auch nach der Bindeoperation für WINDOWS

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

Installieren Sie einen Handler für SIGALRMdann benutze alarm() oder ualarm() vor einer regulären Sperrung recv(). Wenn der Wecker klingelt, die recv() wird einen Fehler mit zurückgeben errno einstellen EINTR.

viveks Benutzeravatar
vivek

Linux

struct timeval tv;
tv.tv_sec = 30;        // 30 Secs Timeout
tv.tv_usec = 0;        // Not init'ing this can cause strange errors
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv,sizeof(struct timeval));

FENSTER

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

HINWEIS: Sie haben diese Einstellung schon einmal vorgenommen bind() Funktionsaufruf für den ordnungsgemäßen Ablauf

  • Diese Frage wurde bereits vor Jahren beantwortet. Welchen neuen Wert bringt Ihre Lösung?

    – Maciej Jureczko

    30. August 2017 um 10:39 Uhr

  • Sie haben diese Einstellung vor dem Funktionsaufruf bind() gesetzt, damit dieser Teil ordnungsgemäß ausgeführt wird. Dieser Teil wird in ans nicht erwähnt

    – vivek

    8. September 2017 um 10:17 Uhr

  • Diese Frage wurde bereits vor Jahren beantwortet. Welchen neuen Wert bringt Ihre Lösung?

    – Maciej Jureczko

    30. August 2017 um 10:39 Uhr

  • Sie haben diese Einstellung vor dem Funktionsaufruf bind() gesetzt, damit dieser Teil ordnungsgemäß ausgeführt wird. Dieser Teil wird in ans nicht erwähnt

    – vivek

    8. September 2017 um 10:17 Uhr

1422790cookie-checkLinux: Gibt es ein Lesen oder Empfangen vom Socket mit Timeout?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy