Co może spowodować Resource temporarily unavailable
błą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!
Odpowiedzi:
"Resource temporarily unavailable"
jest komunikatem o błędzie odpowiadającymEAGAIN
, co oznacza, że operacja byłaby zablokowana, ale zażądano operacji nieblokującej. Nasend()
, które mogą być ze względu na którąkolwiek substancję:fcntl()
; lubMSG_DONTWAIT
flagi dosend()
; lubSO_SNDTIMEO
opcji gniazda.źródło
Dzieje się tak, ponieważ używasz
non-blocking
gniazda, a bufor wyjściowy jest pełny.Od
send()
strony manWhen 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.
EAGAIN to kod błędu powiązany z „Zasób tymczasowo niedostępny”
Rozważ użycie,
select()
aby uzyskać lepszą kontrolę nad tymi zachowaniamiźródło
SO_SNDTIMEO
Podam przykład:
klient łączy się z serwerem i wysyła 1 MB danych do serwera co 1 sekundę.
po stronie serwera zaakceptuje połączenie, a następnie prześpi 20 sekund bez odbioru wiadomości
tcp send buffer
od klienta, więc strona klienta będzie pełna.Kod po stronie klienta:
#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; }
Kod po stronie serwera:
#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); }
Uruchom po stronie serwera, a następnie uruchom po stronie klienta.
po stronie serwera może wyświetlać:
accept a connection from 127.0.0.1:35764 but now I will sleep 15 second, then exit Process finished with exit code 0
po stronie klienta może wyświetlać:
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
Możesz zobaczyć, ponieważ strona serwera nie odzyskuje danych od klienta, więc gdy strona klienta jest
tcp buffer
pełna, ale nadal wysyłasz dane, możesz otrzymaćResource temporarily unavailable
błąd.źródło