2017-10-10 1 views
0

아래 코드에 뭔가 틀린 것이 틀림 없지만 select 문과 함께 사용하여 클라이언트 연결을 사용할 수없는 것 같습니다. 아래 오류 처리의 부족을 무시하십시오. 내가 인터넷 서버의 포트 80에 연결하려고하면BSD 소켓 connect + select (클라이언트)

나는이 문제를 제한 시간 (60)까지 1. 블록을 갖고있는 것 같다 항상 즉시 반환 127.0.0.1에 기존 또는 비 기존 포트를 연결을 시도하는 (2) 성공 또는 실패 여부를 구별 할 방법이없는 선택.

select와 함께 BSD nonblocking에 대한 이해가 부족합니다. 즉, 그것은 진행중인입니다 : 합법적으로 -

fd_set readfds; 
FD_ZERO(&readfds); 

struct timeval tv; 
tv.tv_sec = 60; 
tv.tv_usec = 0; 

struct sockaddr_in dest; 
int socketFD = socket(AF_INET, SOCK_STREAM, 0); 

memset(&dest, 0, sizeof(dest)); 
dest.sin_family = AF_INET; 
dest.sin_addr.s_addr = inet_addr("127.0.0.1"); 
dest.sin_port = htons(9483); 

long arg; 
arg = fcntl(socketFD, F_GETFL, NULL); 
arg |= O_NONBLOCK; 
fcntl(socketFD, F_SETFL, arg); 

if (connect(socketFD, (struct sockaddr *)&dest, sizeof(struct sockaddr))<0 && errno == EINPROGRESS) { 

    //now add it to the read set 
    FD_SET(socketFD, &readfds); 
    int res = select(socketFD+1, &readfds, NULL, NULL, &tv); 

    int error = errno; 
    if (res>0 && FD_ISSET(socketFD, &readfds)) { 
     NSLog(@"errno: %d", error); //Always 36 
    } 
} 

답변

1

errnoconnect에 원래 시도로 설정됩니다. 그런 다음 select으로 전화하십시오. select이 (가)이 아니기 때문에 errno이 (가) 재설정되지 않습니다. 시스템 호출은 실패시에만 errno을 설정합니다. 그들은 성공하면 그것을 지우지 않습니다.

connect이 성공적으로 완료되었을 수 있습니다. 당신은 그것을 확인하지 않습니다. getsockoptSO_ERROR이라는 전화 번호를 추가하여 제대로 작동하는지 확인해야합니다. 그러면 소켓의 오류 상태가 반환됩니다.

다른 중요한 메모 하나. 설명서 페이지 (https://www.freebsd.org/cgi/man.cgi?query=connect&sektion=2)에 따르면 writefds을 사용하여 connect의 완성을 기다려야합니다. readfds이 상태를 올바르게보고할지 여부는 알 수 없습니다.

[EINPROGRESS] The socket is non-blocking and the connection cannot 
       be completed immediately. It is possible to select(2) 
       for completion by selecting the socket for writing. 

이 매우 비슷한 질문을 참조하십시오. Using select() for non-blocking sockets to connect always returns 1

+0

우수 답변! 고마워요! –

관련 문제