2009-05-14 1 views
10

여기 내가 일하고 있어요 일부 코드의 단순화 된 버전입니다 : 우리가 RECV에 대한 첫 번째 호출이 성공한다고 가정하면MSG_PEEK가있는 비 차단 recv가 성공하면 MSG_PEEK이없는 후속 recv도 성공하게됩니까?

void 
stuff(int fd) 
{ 
    int ret1, ret2; 
    char buffer[32]; 

    ret1 = recv(fd, buffer, 32, MSG_PEEK | MSG_DONTWAIT); 

    /* Error handling -- and EAGAIN handling -- would go here. Bail if 
     necessary. Otherwise, keep going. */ 

    /* Can this call to recv fail, setting errno to EAGAIN? */ 
    ret2 = recv(fd, buffer, ret1, 0); 
} 

, 1과 32 사이의 값을 반환 안전하게 두 번째 호출한다고 가정하는 것입니다 또한 성공할 것인가? ret2는 ret1보다 적을 수 있습니까? 어떤 경우에?

recv에 대한 두 번째 호출 중에 다른 오류 조건이 없다고 가정합니다. 신호가 전달되지 않고 ENOMEM이 설정되지 않습니다. 또한 다른 스레드가 fd .

내가 리눅스에있어,하지만 MSG_DONTWAIT 여기, 내가 생각하는 유일한 리눅스 고유의 것입니다. 우측 fnctl가 다른 플랫폼에서 이전에 설정 한 것으로 가정합니다.)

답변

1

내가 EAGAIN 확실하지 않다 EBADF 또는 ECONNRESET이 가능하다고 생각합니다.

+0

다른 스레드가'recv'에 대한 두 번의 호출 사이에서'fd'를 닫지 않으면'EBADF'가 가능하지 않습니다. – pts

7

POSIX 표준은 MSG_PEEK에서 "데이터가 읽지 않은 상태로 처리되고 다음 recv() 또는 유사한 함수가이 데이터를 계속 반환합니다"라는 것을 지정합니다. 그것은 ret2가 -1이 아니면 ret1과 같을 것입니다.

5

다른 스레드에서 다른 recv 호출이 ret1과 ret2 사이에서 호출 될 가능성도 고려해야합니다. 다른 호출은 데이터를 가져오고, ret2는 데이터가 없거나 예기치 않게 적은 데이터로 끝납니다.

앱이 멀티 스레드가 아니거나 fd가이 두 호출에서만 사용되도록 설계된 경우이 것을 무시할 수 있습니다. 그러나 이것이 위험한 것이라면 두 가지 호출을 잠금 메커니즘에 넣어야합니다.

+3

다른 사람이'recv'에 대한이 두 호출 사이에서 데이터를 가져 오는 것은 단일 스레드 프로그램에서도 가능합니다. 동일한 소켓 파일 설명자가 열려있는 다른 프로세스가 데이터를 가져올 수 있습니다. 동일한 프로세스의 신호 처리기가 데이터를 가져올 수도 있습니다. 다행스럽게도 코드의 신호 핸들러는 일반적으로 제어하기 쉽습니다. – pts

0

단순한 경우, 후속 recv은 ret1 바이트 수를 반환합니다 (ret1이 오류가 아닌 경우). 그러나 멀티 스레드 디자인의 경우 항상 그렇지 않을 수도 있습니다.

2

MSG_PEEK없이 recv()를 두 번째 호출하면 신호로 인해 인터럽트 되었기 때문에 EINTR로 실패하거나 불완전한 데이터를 반환 할 수 있습니다.