Co może spowodować „Zasób tymczasowo niedostępny” w poleceniu sock send ()

85

Co może spowodować Resource temporarily unavailablebłąd w send()poleceniu gniazda ? Gniazdo jest skonfigurowane jako AF_UNIX, SOCK_STREAM. Działa przez większość czasu, ale czasami pojawia się ten błąd. Wydaje się, że koniec odbiorczy gniazda działa prawidłowo.

Wiem, że to nie jest zbyt szczegółowe, ale szukam tylko ogólnych pomysłów. Dzięki!

giroy
źródło
Czy to jest powiązane? stackoverflow.com/questions/5737493/…
paddy
4
Czy ustawiasz gniazdo na O_NONBLOCK?
Deepankar Bajpeyi,
Myślę, że nie ma to związku z tym postem. Moje gniazda to SOCK_STREAM, które, jak sądzę, blokują, co chcę.
giroy
3
To, czy strumień jest blokujący, czy nie, jest niezależne od tego, czy jest to SOCK_STREAM czy SOCK_DGRAM. Odpowiedź jest istotna.
Barmar

Odpowiedzi:

96

"Resource temporarily unavailable"jest komunikatem o błędzie odpowiadającym EAGAIN, co oznacza, że ​​operacja byłaby zablokowana, ale zażądano operacji nieblokującej. Na send(), które mogą być ze względu na którąkolwiek substancję:

  • jawne oznaczenie deskryptora pliku jako nieblokującego za pomocą fcntl(); lub
  • przekazanie MSG_DONTWAITflagi do send(); lub
  • ustawienie limitu czasu wysyłania za pomocą SO_SNDTIMEOopcji gniazda.
kawiarnia
źródło
Przyczyną mojego problemu było ustawienie limitu czasu wysyłania. Dziękuję ci za pomoc!
giroy
@caf, W moim przypadku inna konfiguracja rozmiaru MTU po obu stronach powodowała przepełnienie asocjacji sctp Txqueue, gdy zachodziła duża szybkość wymiany pakietów. Zrobienie tego samego MTU w obu systemach sprawiło, że problem zniknął. Ale czy ktoś może wyjaśnić, jaka jest przyczyna problemu?
Codename_DJ
46

Dzieje się tak, ponieważ używasz non-blockinggniazda, a bufor wyjściowy jest pełny.

Od send()strony man

EAGAIN to kod błędu powiązany z „Zasób tymczasowo niedostępny”

Rozważ użycie, select()aby uzyskać lepszą kontrolę nad tymi zachowaniami

Davide Berra
źródło
@giroy: ale właściwie nie w porządku ... właściwie gniazdo blokujące , zSO_SNDTIMEO
EML
Fajnie, ale jak możemy użyć innego połączenia do zarządzania jednoczesnym odczytem w bazie danych?
MUY Belgium,
10

Podam przykład:

  1. klient łączy się z serwerem i wysyła 1 MB danych do serwera co 1 sekundę.

  2. po stronie serwera zaakceptuje połączenie, a następnie prześpi 20 sekund bez odbioru wiadomości tcp send bufferod klienta, więc strona klienta będzie pełna.

Kod po stronie klienta:

Kod po stronie serwera:

Uruchom po stronie serwera, a następnie uruchom po stronie klienta.

po stronie serwera może wyświetlać:

wprowadź opis obrazu tutaj

po stronie klienta może wyświetlać:

wprowadź opis obrazu tutaj

Możesz zobaczyć, ponieważ strona serwera nie odzyskuje danych od klienta, więc gdy strona klienta jest tcp bufferpełna, ale nadal wysyłasz dane, możesz otrzymać Resource temporarily unavailablebłąd.

Jayhello
źródło