2016-08-07 3 views
2

저는 Linux를 사용하고 있습니다.TCP 연결이 정상적으로 닫혔는지 여부를 확인하는 방법 (읽기없이)?

select() 또는 poll()을 사용하여 TCP 연결이 FIN을 통해 피어에 의해 닫혔는지 아니면 RST에 의해 종료되었는지를 확인하는 방법에 대한 예제를 제공 할 수 있습니까?

poll()은 revents에서 POLLHUP 또는 POLLERR을 설정하여 RST를 감지 할 수 있지만 select()에는 이와 같은 기능이 없습니다.

내 테스트에서 소켓이 RST에 의해 종료되면 getsockopt에 의해 소켓 오류가 발생하여 ECONNRESET이됩니다. 이것이 효과적인 방법인가요?

연결이 닫히는 방식을 결정해야합니까?

감사합니다.

+2

"* TCP 연결이 정상적으로 * 피어에 의해 폐쇄 된 경우 확인하는 방법": 또한 당신은 소켓에 보류중인 오류가 있는지 확인하려면이 옵션을 사용할 수있는'RECV()를'0을 반환합니다. – alk

+0

@alk, 소켓에서 읽고 싶지 않습니다. 다른 방법이 있습니까? –

+0

@alk 당신은 -1에 대해 생각하고 있습니다. 0의 리턴이 유효합니다. –

답변

0

소켓이 정상적으로 닫히면 소켓이 읽음으로 설정됩니다. 그런 다음 읽으면 EOF를 받았으므로 읽은 데이터가 0이됩니다. 읽을 데이터가 있는지 확인하려면

ioctl(sock, FIONREAD, &n); 

으로 확인할 수도 있습니다. select man에 따르면 c++ how to use select to see if a socket has closed

: 여기 당신은 예를 들어이 "readfds 문자 읽기를 차단하지 않습니다 있는지 확인하기 위해,보다 정확하게 (읽기 위해 사용할 수있게 있는지 감시한다, 특히, 파일 기술자도 준비 on end of of file) "

보류중인 소켓 오류가 있으면 해당 비트가 readfds 또는 writefds에 설정됩니다. 그런 다음 read 또는 recv가 오류를 반환해야합니다.

if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &result, &resultLen) < 0) { 
    //getsockopt ERROR 
} else if (result == 0) { 
    //NO ERROR 
} else { 
    //SOCKET ERROR 
} 
+0

'ioctl (FIONREAD ...) '은 아무 관계가 없습니다. '정상적으로 닫힘'과 '차단없이 읽을 수있는 데이터가 없습니다'사이에는 차이가 있습니다. – EJP

+0

@EJP, 사용할 수있는 데이터가없는 경우 select는 해당 비트를 readfds로 설정하여 반환하지 않습니다. 사용 가능한 데이터가 있거나 소켓이 정상적으로 닫혀 있거나 보류중인 오류가 있기 때문에 해당 비트가 설정됩니다. 표시된대로 getsockopt를 사용하여 보류 오류를 감지합니다. 오류가 없으면 읽을 수있는 데이터가 있는지 확인합니다. 그런 다음 사용할 수있는 데이터가없는 유일한 이유는 소켓이 닫혀 있기 때문입니다. – rodolk

+0

또는 다른 스레드가 당신을 읽고 그것에 이겼습니다. 올바른 기술은'recv()'를 수행하고 제로 리턴 값을 식별하는 것이다.이런 트릭은 신뢰할 수없고 무의미합니다. – EJP