2014-01-09 6 views
6

(성능 수준에서) 더 좋은 소켓 syscall (예 : recv) 오류가 발생 했습니까?SO_ERROR 대 errno

  • 는 평범한 구식 errno
  • 사용 또는 getsockopt()의 optname로 SO_ERROR을 사용할 수 있습니까?

시스템 호출이 아니기 때문에 errno (내 시스템에서는 __error()으로 정의 됨)이 더 빠르다고 생각합니다. 내가 맞습니까?

SO_ERROR의 장점은 다음과 같습니다. 가져 오기 후 자동 오류 재설정, 우리는 오류가 우리 소켓에만 관련된 것임을 확신합니다. 더 안전합니다.

어느 것이 좋을까요? 이 둘 사이에 실제 성능 차이가 있습니까?

+0

SO_ERROR에 대한 요점은 다른 시스템 호출 (예 :'select()'도 호출 한 후에도 소켓 데이터에 안전하게 빠져 나갔다는 것인데,'errno'도 설정할 수 있습니다. – EJP

답변

4

Dan Bernstein을 인용 :

상황을 : 당신은 비 블로킹 소켓을 설정하고 -1 반환/EINPROGRESS -1/EWOULDBLOCK이) (A 연결을한다. 쓰기 가능하도록 소켓을 선택()합니다. 이것은 연결이 성공 또는 실패하는 즉시 반환됩니다. (예외 : 일부 이전 버전의 Ultrix에서는 select()가 75 초의 시간 초과 전에 실패를 감지하지 못합니다.)

질문 : select()가 쓰기 기능을 반환 한 후에 무엇을합니까? 연결이 실패 했습니까? 그렇다면 어떻게 실패 했습니까?

연결이 실패하면 소켓의 so_error라는 부분에 이유가 숨겨집니다. 현대 시스템은

그는 getsockopt(,,SO_ERROR,,) 오래된 시스템에서 작동하는 방법과 얻는하지 않는 현대의 발명이 사실을 논의하기 위해 계속 ... 당신이 getsockopt 함수 (,, SO_ERROR ,,)와 SO_ERROR를 보자 그러한 시스템의 오류 코드. 그러나 지난 15 년 동안 유닉스/리눅스 시스템을 프로그래밍하고 있다면 걱정할 필요가 없을 것입니다.

connect에 대한 Linux 매뉴얼 페이지는 SO_ERROR과 동일한 사용법을 설명합니다.

소켓에서 비동기 작업을 수행하는 경우 일 수 있습니다.SO_ERROR을 사용해야합니다. 다른 경우에는 errno을 사용하십시오. 유닉스 네트워크 프로그래밍 인용

+0

Dan Bernstein은 'Ultrix의 이전 버전'에 대해서는 올바르지 않습니다. 75 초 제한 시간이 아직 남아 있습니다. select()는 피어에 의한 * 거절 *이 있으면 먼저 연결 실패를 감지합니다 (예 : 응답). 응답이 전혀 없으면 시간 초과가 계속 적용됩니다. 정확한 타임 아웃 기간은 플랫폼에 따라 다릅니다. – EJP

+0

@EJP : 타임 아웃이 응답없이 통과 할 때까지 아무런 실패가 없습니다. –

+0

@EJP djb의 요점은 거절이 언제 일어 났는지에 관계없이 75 초 제한 시간이 만료 될 때까지 Ultrix의 일부 구 버전이 활성 거절 (예 : RST 패킷)을보고하지 않는다고 생각합니다. 이는 Ultrix 또는 다른 시스템이 응답이 없는데도 75 초가 지나면 실패를보고하는지 여부와는 무관합니다. –

0

:

프로세스 호출을 읽고 반환 할 데이터가없는 경우 SO_ERROR이 0이 아닌 경우, SO_ERROR 의 값 (P로 설정 반환-1 errno를 읽기 TCPv2의 516). so_error의 값은 0으로 다시 설정됩니다. 이 소켓에 대기중인 데이터 인 경우 해당 데이터는 오류 상태 인 대신 읽음으로 반환됩니다. 프로세스가 쓰기를 호출 할 때 so_error가 0이 아닌 경우, -1이 리턴되고 errno는 so_error 값으로 설정되고 (TCPv2의 495 ), so_error는 0으로 재설정됩니다.

데이터를 완전히 가져 오기 전에 즉시 오류를 얻지 않으려면 errno를 선택하는 것이 좋습니다.