sock send () 명령에서 "일시적으로 리소스를 사용할 수 없음"이 발생하는 원인
Resource temporarily unavailable
소켓 send()
명령 에 오류 가 발생할 수있는 것은 무엇입니까 ? 소켓은 AF_UNIX, SOCK_STREAM
. 대부분의 경우 작동하지만 때때로이 오류가 발생합니다. 소켓의받는 쪽이 제대로 작동하는 것 같습니다.
나는 이것이 그다지 상세하지 않다는 것을 알고 있지만 일반적인 아이디어를 찾고 있습니다. 감사!
"Resource temporarily unavailable"
에 해당하는 오류 메시지 EAGAIN
입니다. 이는 작업이 차단되었지만 비 차단 작업이 요청되었음을 의미합니다. 의 경우 다음 send()
중 하나 때문일 수 있습니다.
- 파일 설명자를 비 차단으로 명시 적으로 표시합니다
fcntl()
. 또는 - 통과
MSG_DONTWAIT
플래그를합니다send()
; 또는 SO_SNDTIMEO
소켓 옵션 으로 전송 시간 제한을 설정합니다 .
non-blocking
소켓을 사용하고 있고 출력 버퍼가 가득 차 있기 때문 입니다.
로부터 send()
man 페이지
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의 데이터를 서버에 보냅니다.
서버 측은 연결을 수락 한 다음
tcp send buffer
클라이언트 의 recv msg없이 20 초 동안 잠자기 때문에 클라이언트 측은 가득 찰 것입니다.
클라이언트 측 코드 :
#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
You can see, as the server side doesn't recv the data from client, so when the client side tcp buffer
get full, but you still send data, so you may get Resource temporarily unavailable
error.
'Development Tip' 카테고리의 다른 글
java, spring, hibernate, maven과 관련된 읽기 좋은 블로그는 무엇입니까? (0) | 2020.10.29 |
---|---|
이상한 배열 반환 유형 (0) | 2020.10.29 |
JSLint / JSHint에게 이미 정의 된 전역 변수를 알리는 방법 (0) | 2020.10.29 |
사용하지 않을 때 SQL Azure DB 중지 (0) | 2020.10.29 |
angular2를 사용하여 서비스에서 구성 요소의 변수 변경 사항 업데이트 (0) | 2020.10.29 |