Was kann eine „Ressource vorübergehend nicht verfügbar“ beim Befehl sock send() verursachen

Lesezeit: 6 Minuten

Benutzeravatar von giroy
Giroy

Wodurch kann a Resource temporarily unavailable Fehler auf einem Socket send() Befehl? Die Buchse ist eingerichtet als AF_UNIX, SOCK_STREAM. Es funktioniert die meiste Zeit, aber gelegentlich tritt dieser Fehler auf. Das empfangende Ende des Sockets scheint ordnungsgemäß zu funktionieren.

Ich weiß, das ist nicht sehr detailliert, aber ich suche nur nach allgemeinen Ideen. Vielen Dank!

  • Ist das verwandt? stackoverflow.com/questions/5737493/…

    – Reisfeld

    17. Januar 2013 um 0:52 Uhr

  • Setzen Sie Ihren Socket auf O_NONBLOCK?

    – Deepankar Bajpeyi

    17. Januar 2013 um 0:57 Uhr

  • Ich glaube nicht, dass es mit diesem Beitrag zusammenhängt. Meine Sockets sind SOCK_STREAM, von denen ich glaube, dass sie blockieren, was ich will.

    – giro

    17. Januar 2013 um 0:59 Uhr


  • Ob ein Stream blockiert oder nicht blockiert, ist unabhängig davon, ob es sich um SOCK_STREAM oder SOCK_DGRAM handelt. Die Antwort dort ist relevant.

    – Barmar

    17. Januar 2013 um 1:33 Uhr

"Resource temporarily unavailable" ist die entsprechende Fehlermeldung EAGAIN, was bedeutet, dass der Vorgang blockiert wäre, aber ein nicht blockierender Vorgang angefordert wurde. Zum send()das könnte an Folgendem liegen:

  • explizites Markieren des Dateideskriptors als nicht blockierend mit fcntl(); oder
  • vorbei an der MSG_DONTWAIT Flagge zu send(); oder
  • Einstellen eines Sende-Timeouts mit der SO_SNDTIMEO Steckdosenoption.

  • Die Ursache meines Problems war das Einstellen des Sende-Timeouts. Danke für deine Hilfe!

    – giro

    17. Januar 2013 um 22:58 Uhr

  • @caf, In meinem Fall führte eine unterschiedliche MTU-Größenkonfiguration auf zwei Seiten dazu, dass die sctp-Assoziations-Txqueue überflog, wenn eine hohe Paketaustauschrate stattfand. Wenn Sie die MTU auf beiden Systemen gleich machten, verschwand das Problem. Aber kann mir bitte jemand erklären, was der Grund für das Problem ist?

    – Codename_DJ

    23. Januar 2017 um 12:22 Uhr


  • Warum verursacht das Setzen von SO_SNDTIMEO den Fehler? Wie verwendet man diese Flagge richtig?

    – Gabriel Fernández

    27. April 2021 um 20:10 Uhr

  • @GabrielFernandez: Weil das was ist SO_SNDTIMEO Anfragen: dass die Sendung nicht länger als die Timeout-Periode blockiert. Wenn das Senden nicht abgeschlossen ist und das Timeout abläuft, wird es zurückgegeben EAGAIN um diesen Zustand anzuzeigen. Wie Sie damit umgehen, hängt von Ihrer Bewerbung ab, wobei zu beachten ist, dass die von Ihnen versuchten Daten nicht gesendet wurden.

    – Café

    28. April 2021 um 7:13 Uhr

Das liegt daran, dass Sie a verwenden non-blocking Socket und der Ausgabepuffer ist voll.

Von dem send() Manpage

   When the message does not fit into  the  send  buffer  of  the  socket,
   send() normally blocks, unless the socket has been placed in non-block-
   ing I/O mode.  In non-blocking mode it  would  return  EAGAIN  in  this
   case.  

WIEDER ist der zugehörige Fehlercode “Ressource vorübergehend nicht verfügbar”

Erwägen Sie die Verwendung select() eine bessere Kontrolle über dieses Verhalten zu bekommen

  • @giroy: aber eigentlich nicht richtig … eigentlich a Blockierung Steckdose, mit SO_SNDTIMEO

    – EML

    12. Juli 2018 um 7:22 Uhr

  • Cool, aber wie können wir eine andere Verbindung verwenden, um das gleichzeitige Lesen in der DB zu verwalten?

    – MUY Belgien

    16. September 2019 um 12:09 Uhr

Lassen Sie mich ein Beispiel geben:

  1. Der Client stellt eine Verbindung zum Server her und sendet alle 1 Sekunde 1 MB Daten an den Server.

  2. Die Serverseite akzeptiert eine Verbindung und schläft dann 20 Sekunden lang ohne Empfangsnachricht vom Client.So die tcp send buffer auf der Clientseite wird voll sein.

Code auf der Clientseite:

#include <arpa/inet.h>
#include <sys/socket.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#define exit_if(r, ...)                                                                          \
    if (r) {                                                                                     \
        printf(__VA_ARGS__);                                                                     \
        printf("%s:%d error no: %d error msg %s\n", __FILE__, __LINE__, errno, strerror(errno)); \
        exit(1);                                                                                 \
    }

void setNonBlock(int fd) {
    int flags = fcntl(fd, F_GETFL, 0);
    exit_if(flags < 0, "fcntl failed");
    int r = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
    exit_if(r < 0, "fcntl failed");
}

void test_full_sock_buf_1(){
    short port = 8000;
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof addr);
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = INADDR_ANY;


    int fd = socket(AF_INET, SOCK_STREAM, 0);
    exit_if(fd<0, "create socket error");

    int ret = connect(fd, (struct sockaddr *) &addr, sizeof(struct sockaddr));
    exit_if(ret<0, "connect to server error");
    setNonBlock(fd);

    printf("connect to server success");

    const int LEN = 1024 * 1000;
    char msg[LEN];  // 1MB data
    memset(msg, 'a', LEN);

    for (int i = 0; i < 1000; ++i) {
        int len = send(fd, msg, LEN, 0);
        printf("send: %d, erron: %d, %s \n", len, errno, strerror(errno));
        sleep(1);
    }

}

int main(){
    test_full_sock_buf_1();

    return 0;
}

Code auf der Serverseite:

    #include <arpa/inet.h>
    #include <sys/socket.h>
    #include <stdio.h>
    #include <errno.h>
    #include <fcntl.h>
    #include <stdlib.h>
    #include <string.h>
    #define exit_if(r, ...)                                                                          \
        if (r) {                                                                                     \
            printf(__VA_ARGS__);                                                                     \
            printf("%s:%d error no: %d error msg %s\n", __FILE__, __LINE__, errno, strerror(errno)); \
            exit(1);                                                                                 \
        }
void test_full_sock_buf_1(){

    int listenfd = socket(AF_INET, SOCK_STREAM, 0);
    exit_if(listenfd<0, "create socket error");

    short port = 8000;
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof addr);
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = INADDR_ANY;

    int r = ::bind(listenfd, (struct sockaddr *) &addr, sizeof(struct sockaddr));
    exit_if(r<0, "bind socket error");

    r = listen(listenfd, 100);
    exit_if(r<0, "listen socket error");

    struct sockaddr_in raddr;
    socklen_t rsz = sizeof(raddr);
    int cfd = accept(listenfd, (struct sockaddr *) &raddr, &rsz);
    exit_if(cfd<0, "accept socket error");

    sockaddr_in peer;
    socklen_t alen = sizeof(peer);
    getpeername(cfd, (sockaddr *) &peer, &alen);

    printf("accept a connection from %s:%d\n", inet_ntoa(peer.sin_addr), ntohs(peer.sin_port));

    printf("but now I will sleep 15 second, then exit");
    sleep(15);
}

Serverseitig starten, dann clientseitig starten.

Serverseite kann Folgendes ausgeben:

accept a connection from 127.0.0.1:35764
but now I will sleep 15 second, then exit
Process finished with exit code 0

Geben Sie hier die Bildbeschreibung ein

Clientseite kann Folgendes ausgeben:

connect to server successsend: 1024000, erron: 0, Success 
send: 1024000, erron: 0, Success 
send: 1024000, erron: 0, Success 
send: 552190, erron: 0, Success 
send: -1, erron: 11, Resource temporarily unavailable 
send: -1, erron: 11, Resource temporarily unavailable 
send: -1, erron: 11, Resource temporarily unavailable 
send: -1, erron: 11, Resource temporarily unavailable 
send: -1, erron: 11, Resource temporarily unavailable 
send: -1, erron: 11, Resource temporarily unavailable 
send: -1, erron: 11, Resource temporarily unavailable 
send: -1, erron: 11, Resource temporarily unavailable 
send: -1, erron: 11, Resource temporarily unavailable 
send: -1, erron: 11, Resource temporarily unavailable 
send: -1, erron: 11, Resource temporarily unavailable 
send: -1, erron: 104, Connection reset by peer 
send: -1, erron: 32, Broken pipe 
send: -1, erron: 32, Broken pipe 
send: -1, erron: 32, Broken pipe 
send: -1, erron: 32, Broken pipe 
send: -1, erron: 32, Broken pipe 

Geben Sie hier die Bildbeschreibung ein

Sie können sehen, dass die Serverseite die Daten nicht vom Client empfängt, also wenn die Clientseite tcp buffer voll werden, aber Sie senden immer noch Daten, damit Sie möglicherweise erhalten Resource temporarily unavailable Error.

Es gibt einen anderen Fall, der Fehler 11 verursachen kann Resource temporarily unavailable

Wenn das Protokoll der Anwendungsschicht http ist, wird die TCP-Verbindung nach dem erfolgreichen Empfang der ersten http-Antwort standardmäßig nicht geschlossen, der Anrufempfang wird erneut blockiert und -1 wird von recv zurückgegeben, wenn SO_RCVTIMEO abgelaufen ist, errno wird gesetzt 11

1420830cookie-checkWas kann eine „Ressource vorübergehend nicht verfügbar“ beim Befehl sock send() verursachen

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

Privacy policy