Что может вызвать Resource temporarily unavailable
ошибку в send()
команде сокета ? Сокет настроен как AF_UNIX, SOCK_STREAM
. В большинстве случаев это работает, но иногда возникает эта ошибка. Принимающий конец розетки работает правильно.
Я знаю, что это не очень подробно, но я просто ищу общие идеи. Благодаря!
Ответы:
"Resource temporarily unavailable"
- сообщение об ошибке, соответствующее значкуEAGAIN
, что означает, что операция была бы заблокирована, но была запрошена неблокирующая операция. Ибоsend()
это может быть связано с одним из следующих факторов:fcntl()
; или жеMSG_DONTWAIT
флагаsend()
; или жеSO_SNDTIMEO
параметра сокета.источник
Это потому, что вы используете
non-blocking
сокет, а выходной буфер заполнен.Со
send()
страницы руководства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.
EAGAIN - это код ошибки, привязанный к "Ресурс временно недоступен"
Рассмотрите возможность использования,
select()
чтобы лучше контролировать это поведениеисточник
SO_SNDTIMEO
Приведу пример:
клиент подключается к серверу и отправляет на сервер 1 МБ данных каждые 1 секунду.
сторона сервера принимает соединение, а затем спит 20 секунд, без сообщения recv от клиента. Таким образом,
tcp send buffer
на стороне клиента будет заполнено.Код на стороне клиента:
#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; }
Код на стороне сервера:
#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); }
Запустить на стороне сервера, затем запустить на стороне клиента.
сторона сервера может выводить:
accept a connection from 127.0.0.1:35764 but now I will sleep 15 second, then exit Process finished with exit code 0
сторона клиента может выводить:
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
Вы можете видеть, как серверная сторона не получает данные от клиента, поэтому, когда клиентская сторона
tcp buffer
заполняется, вы все равно отправляете данные, поэтому вы можете получитьResource temporarily unavailable
ошибку.источник