2010-07-07 1 views
5

TCP 소켓 프로그래밍에서 recv()이 0이면 다른 쪽이 연결을 종료했음을 나타냅니다. 그러나 AFAIK, TCP RFC는 TCP의 페이로드를 0보다 크게 요구하지 않습니다. 따라서 이론적으로 TCP 스택은 페이로드가 0 인 메시지를 수신 할 수 있습니다.페이로드 크기가 0 인 유효한 TCP 패킷을 수신하면 recv() 값이 반환됩니다.

기본적으로 내 질문은 recv() 페이로드 크기가 0 인 패킷을 수신합니까? 0을 반환하면 닫힌 연결 표시와 어떻게 구별 할 수 있습니까?

답변

11

페이로드 크기가 0 인 TCP 세그먼트는 유비쿼터스입니다. 실제 TCP 스트림은 거의 모든 곳에서 발생합니다. 한쪽이 다른 쪽에서 데이터를 수신했음을 알리려고 할 때마다 전송되지만 자체 데이터를 보낼 데이터는 없습니다. (이들은 일반적으로 "ACK 패킷"이라고 알려져 있지만 "ACK 패킷"은 데이터가없는 일반 세그먼트입니다).

이러한 패킷에는 사용자 응용 프로그램에 전달할 데이터가 없기 때문에 recv()은 실제 데이터가 도착할 때까지 계속 차단됩니다. recv()이 0을 반환하면 다른 쪽 끝이 연결 측면을 닫았으며 더 이상 데이터를 보내지 않을 것이라는 명확한 표시입니다.

TCP는 스트림 지향입니다. 이 아니며은 단일 recv() 호출로 반환 된 데이터와 단일 TCP 세그먼트의 데이터 사이에 일 대 일 매핑을 나타냅니다. 단일 recv() 호출은 여러 TCP 세그먼트와 겹치는 데이터 블록을 반환 할 수 있으며 여러 개의 recv() 호출에서 단일 TCP 세그먼트의 데이터가 반환 될 수 있습니다. TCP 세그먼트 사이의 경계는 BSD 소켓 API를 사용하는 응용 프로그램에서 볼 수 없습니다. 그러한 경계가 필요하면 TCP 스트림 내에서 응용 프로그램 계층 프로토콜을 사용하여 직접 구현하거나 UDP와 같은 데이터 그램 지향 프로토콜을 사용해야합니다.

+0

+1은 ACK를 언급합니다. –

+0

ACK 패킷에는 ACK 플래그가 설정됩니다. – AlastairG

+1

@AlastairG : 그렇습니다. 그러나 초기 SYN 또는 연결 재설정 이외의 모든 패킷에는 'ACK'비트가 설정되어 있습니다. – caf

3

오른쪽, recv0을 반환하면 POSIX에 따라 연결이 피어에 의해 올바르게 종료됩니다. 누군가가 0 크기의 페이로드와 TCP 패킷을 보내도록 관리하는 경우

는 다음 OS 는 소켓 recv 시스템 호출에 차단되는 프로세스에 데이터를를 반환 할 필요가 없습니다.

TCP 페이로드는 단일 시스템 호출 중에 반환되어야하는 데이터 그램 시퀀스가 ​​아닌 OS에 의해 무작위로 슬라이스 될 수있는 연속 스트림을 형성 함을 기억하십시오.

관련 문제