Was kann einen Resource temporarily unavailable
Fehler bei einem Socket- send()
Befehl verursachen? Die Steckdose ist eingerichtet als AF_UNIX, SOCK_STREAM
. Es funktioniert die meiste Zeit, aber gelegentlich wird dieser Fehler angezeigt. Das Empfangsende der Buchse scheint ordnungsgemäß zu funktionieren.
Ich weiß, dass dies nicht sehr detailliert ist, aber ich suche nur nach allgemeinen Ideen. Vielen Dank!
Antworten:
"Resource temporarily unavailable"
ist die entsprechende FehlermeldungEAGAIN
, was bedeutet, dass die Operation blockiert worden wäre, aber eine nicht blockierende Operation angefordert wurde. Dennsend()
das könnte folgende Ursachen haben:fcntl()
; oderMSG_DONTWAIT
Flagge ansend()
; oderSO_SNDTIMEO
Socket-Option.quelle
Das liegt daran, dass Sie einen
non-blocking
Socket verwenden und der Ausgabepuffer voll ist.Von der
send()
ManpageWhen 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 ist der Fehlercode, der an "Ressource vorübergehend nicht verfügbar" gebunden ist.
Erwägen Sie die Verwendung
select()
, um eine bessere Kontrolle über dieses Verhalten zu erhaltenquelle
SO_SNDTIMEO
Lassen Sie mich ein Beispiel geben:
Der Client stellt eine Verbindung zum Server her und sendet alle 1 Sekunde 1 MB Daten an den Server.
Die Serverseite akzeptiert eine Verbindung und schläft dann 20 Sekunden lang, ohne eine Nachricht vom Client zu erhalten. Die
tcp send buffer
auf der Clientseite ist also voll.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); }
Starten Sie die Serverseite und dann die Clientseite.
Die 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
Client-Seite kann 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
Sie können sehen, dass die Serverseite die Daten vom Client nicht abruft. Wenn also die Clientseite
tcp buffer
voll wird, Sie aber dennoch Daten senden, wird möglicherweise einResource temporarily unavailable
Fehler angezeigt .quelle