2009-07-08 3 views
2

업데이트 흐름. 내가 얻는 오류는 EINPROGRESS가 아닌 ECONNREFUSED입니다. error 변수를 확인한 결과 0보다 큰 것으로 확인되었으므로 error 대신 errno을 인쇄했습니다. 물론 은 connect()에 대한 호출 이후 값이 변경되지 않았기 때문에 EINPROGRESS입니다.getsockopt 함수는() 연결 비 블로킹에 EINPROGRESS를 반환() + 선택()

질문에 답변했습니다. 고마워요.

내가 연결 차단> 스티븐스 UNIX 네트워크 프로그래밍 아닌 같이 코드하여 같은 조각을 사용하고() 예 :

  1. 이 (
  2. 가 블로킹 연결 함 앤지 비 블로킹에 소켓을 설정)
  3. 즉시 완료
  4. 확인
  5. 전화를 선택() 타임 아웃 등) (일부는 버지니아로 돌아 오면
  6. 준비 읽기 기다리거나 쓰기 0보다 큰 값은 getsockopt (socket, SOL_SOCKET, SO_ERROR, & 오류, & len)입니다.

오류는 EINPROGRESS입니다. 코드는 rhel5 서버에서 실행됩니다.

이 오류가 발생하는 이유는 무엇입니까?

코드 스 니펫 : 0보다 큰

flags = fcntl(sockfd, F_GETFL, 0); 
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); 

if ((retVal = connect(sockfd, saptr, salen)) < 0) 
    if (errno != EINPROGRESS) 
    return (-1); 

if (retVal == 0) 
{ 
    // restore file status flags 
    fcntl(sockfd, F_SETFL, flags); 
    return 0; 
} 

FD_ZERO(&rset); 
FD_SET(sockfd, &rset); 
wset = rset; 
tval.tv_sec = nsec; 
tval.tv_usec = 0; 

if ((retVal = select(sockfd + 1, &rset, &wset, NULL, &tval)) == 0) 
{ 
    // timeout 
    close(sockfd);   
    errno = ETIMEDOUT; 
    return (-1); 
} 

if (retVal < 0) 
{ 
    // select() failed 
    return (-1); 
} 

if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) 
{ 
    len = sizeof(error); 
    error = 0; 
    if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) 
    return (-1);  

    if (error > 0) //<<<<< error == EINPROGRESS >>> 
    { 
    close(sockfd); 
    errno = error; 
    return (-1); 
    } 
} 
else 
{ 
    return (-1); 
} 

// restore file status flags 
fcntl(sockfd, F_SETFL, flags); 
+0

을 공유하십시오. 어쩌면 관련 코드 스 니펫을 게시해야합니다. – Duck

+1

예기치 않은 일이 있습니까? non-blocking'connect'는 연결이 완료 될 때까지'EINPROGRESS'를보고합니다. 이것은 man 페이지의'connect'에 문서화되어 있습니다. – ephemient

+0

@ephemient : 연결에 대한 하위 호출이 EALREADY를 반환합니까? –

답변

3

Shucks .... 나는 포기합니다. 시도했지만 시도했지만 코드에 문제가 없습니다. 그래서 제가 제안하는 것은 몇 가지 제안과 가설입니다.

  • rset을 wset으로 복사하려면 FD_COPY를 사용하십시오.

  • 첫 번째 연결이 실패 할 때 getsockopt를 할 수 있습니까? Select가 0을 반환하고 위의 이유로 인해 어떻게 든 writefd 세트가 설정되고 getsockopt가 이전 연결의 부실 오류를 반환하는 것으로 의심됩니다.IMO하는 subsquent가 EALREADY (종속이 될 수 있지만 플랫폼)를 반환해야합니다 연결

위의을 (내가 FD_COPY 사용에 대한 잘못된 생각하면 나를 downvote)이 올바른 소리 결과

+4

Aditya, 문제를 발견하고 문제의 설명과 함께 원래의 질문을 편집했습니다. 그것은 나쁘다. 나는 "if (error> 0)"블럭 안의 잘못된 값을 printfed했다 (관련 printf는 코드 스 니펫에서 no이다). 당신의 도움을 주셔서 대단히 감사합니다. – mrvincenzo

+0

큰 직장. 그럼 모두 잘합니다. –

2

셀렉트 값은 오류의 종류를 표시하지 않습니다 ... 그것은 선택 문의 기준을 충족 소켓의 수입니다. select는 실패한 경우 -1을 반환합니다.

SO_ERROR로 getsocktopt를 호출하면 유효하지 않습니다. 소켓을 사용할 때마다 오류를 검사하는 것이 가장 좋습니다. (어쨌든하고 있다고 생각합니다.) 그것은 선택이 실패하지 않습니다, 당신은 괜찮아요.

+0

select()에는 문제가 없습니다. getsockopt()에 대한 호출은 nonblock connect()가 성공했는지 여부를 확인하기 위해 여기에서 이루어집니다. 제 경우에는 그렇지 않았습니다. – mrvincenzo

2

EINPROGRESS는 non-blocking connect()가 아직 진행 중임을 나타냅니다.

그래서 내가 물어볼 것입니다 - 선택() 반환 후 connect() 파일 설명자가 writefds fd_set 여전히 설정되어 있는지 확인합니까? 그렇지 않으면 select()가 다른 이유로 반환 된 것을 의미합니다.

관련 문제