![](/img/trans.png)
[英]What can cause a “Resource temporarily unavailable” on sock connect() command
[英]What can cause a “Resource temporarily unavailable” on sock send() command
什么會導致套接字send()
命令上的Resource temporarily unavailable
錯誤? 套接字設置為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()
來更好地控制這種行為
讓我舉個例子:
客戶端連接到服務器,每 1 秒發送 1MB 數據到服務器。
服務器端接受一個連接,然后休眠 20 秒,沒有來自客戶端的 recv msg。因此客戶端的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
錯誤。
還有一種情況會導致錯誤 11 Resource temporarily unavailable
By default, if application layer protocol is http, after first http response recv successfully, tcp connection won't be close, call recv again will be blocked and -1 will returned from recv when SO_RCVTIMEO expired, errno will be set 11
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.