¿Qué puede causar un Resource temporarily unavailable
error en un send()
comando de socket ? El enchufe está configurado como AF_UNIX, SOCK_STREAM
. Funciona la mayor parte del tiempo, pero ocasionalmente recibe este error. El extremo receptor del enchufe parece funcionar correctamente.
Sé que esto no es muy detallado, pero solo estoy buscando ideas generales. ¡Gracias!
Respuestas:
"Resource temporarily unavailable"
es el mensaje de error correspondiente aEAGAIN
, lo que significa que la operación se habría bloqueado pero se solicitó la operación sin bloqueo. Porquesend()
, eso podría deberse a cualquiera de:fcntl()
; oMSG_DONTWAIT
bandera asend()
; oSO_SNDTIMEO
opción de socket.fuente
Eso es porque estás usando un
non-blocking
socket y el búfer de salida está lleno.Desde la
send()
página del manualWhen 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 es el código de error vinculado a "Recurso temporalmente no disponible"
Considere usar
select()
para obtener un mejor control de estos comportamientosfuente
SO_SNDTIMEO
Déjame darte un ejemplo:
el cliente se conecta al servidor y envía 1 MB de datos al servidor cada segundo.
El lado del servidor acepta una conexión y luego duerme 20 segundos, sin recibir el mensaje
tcp send buffer
del cliente. Por lo tanto, el lado del cliente estará lleno.Código en el lado del cliente:
#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; }
Código en el lado del servidor:
#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); }
Inicie el lado del servidor, luego inicie el lado del cliente.
el lado del servidor puede generar:
accept a connection from 127.0.0.1:35764 but now I will sleep 15 second, then exit Process finished with exit code 0
el lado del cliente puede generar:
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
Como puede ver, como el lado del servidor no recupera los datos del cliente, cuando el lado del cliente
tcp buffer
se llena, pero aún envía datos, puede obtener unResource temporarily unavailable
error.fuente