현재 TCP 연결을 여는 메소드에 시간 초과를 추가하려고합니다. 나는 대충 선택 가이드 대신 poll()
을 사용하려고한다는 것을 제외하고는 here이라는 가이드를 사용하고 있습니다. 그러나 poll()
을 호출하면 연결이 열려 있지 않아도 fd가 쓰기 준비가되었음을 알리는 즉시 반환됩니다. 포트 49999
내 컴퓨터에 닫혀폴링을 사용하는 TCP 시간 초과
#include <cstring>
#include <poll.h>
#include <unistd.h>
#include <fcntl.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <cerrno>
#include <iostream>
#include <cstdlib>
int main() {
struct addrinfo hints;
::memset(&hints, 0, sizeof(hints));
hints.ai_socktype = 0;
hints.ai_family = AF_UNSPEC;
hints.ai_protocol = 0;
hints.ai_flags = AI_CANONNAME;
struct addrinfo * info;
if(::getaddrinfo("127.0.0.1", "49999", &hints, &info) != 0) {
std::cerr << "Error: getaddrinfo" << std::endl;
exit(1);
}
int soc;
if((soc = ::socket(info->ai_family, info->ai_socktype, info->ai_protocol)) < 0) {
std::cerr << "Erorr: socket" << std::endl;
}
// Set mode to non-blocking for timeout handling
int arg;
if((arg = ::fcntl(soc, F_GETFL, 0)) < 0) {
std::cerr << "Error: fcntl" << std::endl;
exit(1);
}
arg |= O_NONBLOCK;
if(::fcntl(soc, F_SETFL, arg) < 0) {
std::cerr << "Error: fcntl" << std::endl;
exit(1);
}
int res = ::connect(soc,info->ai_addr,info->ai_addrlen);
if((res != 0) && (errno != EINPROGRESS)) {
std::cerr << "Error: connect" << std::endl;
exit(1);
}
pollfd pfd;
pfd.fd = soc;
pfd.events = POLLOUT;
res = ::poll(&pfd, 1, 50000);
if(res < 0) {
std::cerr << "Error: poll" << std::endl;
exit(1);
}
else if(res == 0) {
std::cerr << "Error: poll" << std::endl;
exit(1);
}
// Set blocking mode again
if((arg = ::fcntl(soc, F_GETFL, NULL)) < 0) {
std::cerr << "Error: fcntl" << std::endl;
exit(1);
}
arg &= (~O_NONBLOCK);
if(::fcntl(soc, F_SETFL, arg) < 0) {
std::cerr << "Error: fcntl" << std::endl;
exit(1);
}
return 0;
}
때문에 나는 오류를 기대 : 여기에 내가 생성 된 감소 코드 예입니다. 대신 프로그램은 0
의 반환 값으로 끝납니다.
또한 위의 링크에서 발견 된 선택 예제를 사용하려고했습니다.
Operation now in progress: Operation now in progres
내가 선택 사용하여 코드를 줄이기 위해 노력했다,하지만 난 그것을 줄일 때, 나는 올바른 connection refused message
를 얻을 : 나는 전체 예제를 poll()
에 전화를 교체 할 경우 나는 다음과 같은 오류 메시지가 나타납니다.
편집 :
참고 : "작업을 현재 진행 중"메시지가 내 옆에 오류 처리 코드의 오류 때문. 이 문제를 해결하면 getsockopt()에서 올바른 오류 메시지를 받았습니다. 또한이 예제를 왜 줄일 수 없었는지에 대해서도 설명합니다.
"connect()가 성공하지 못하면 poll()이 오류를 반환한다고 가정합니다." 당신이 잘못했다고 생각했습니다. 'connect()'는 소켓을 쓰기 가능하게하거나 타임 아웃이 끝날 때까지 블럭을 제외하고 아무것도하지 않는다. 실패했을 때 오류를 반환하고 코드가 올바르게 검사하지 않으면'connect()'입니다. 'connect()'가'EAGAIN'을 리턴했다면 폴링만으로이를 고쳤습니다. 다른 말로하면 내 대답을 구현했습니다. 당신이 그것을 깨닫는 지 안하든. – EJP
예, 오류가 반환된다고 가정하는 것은 잘못되었습니다. 그러나 'EINPROGRESS'에 대한 누락 된 체크는 나를 혼란스럽게하는 문제가 아닙니다. 나중의 테스트에서, 코드는 항상'fprintf (stderr, "지연 연결 (% d - % s \ n", valopt, strerror (valopt));에 오류가 발생했습니다. 그래서'EINPROGRESS '는'getsockopt()'를 사용하여 검사를했기 때문에 아무것도하지 않았을 것입니다 (또는 다른 경우에는 그 라인이 잘못되었습니다). 아직도 잠재적 인 미래의 버그에 대해 경고 해 주었고 나중에 버그를 디버깅 할 수있었습니다. – LiKao