본문 바로가기

C/C++

소켓통신함수 Socket close()와 shutdown() 차이

출처: http://iblog.or.kr/hungi/it/software/programing/466/comment-page-1#comment-2206


int close( int sockfd );


소켓을 닫고 통신을 종료합니다. sockfd는 닫을 소켓 번호입니다.

성공하면 0을 실패하면 -1을 반환합니다.

닫힌 소켓은 더 이상 사용할 수 없습니다.

내부적으로 TCP는 send buffer 와 recv buffer가 있습니다.

만약에 close를 호출 하였는데 send buffer에 보낼 데이터가 남아 있으면

그것을 모두 보낸 후에 앞서 설명 드린 TCP 연결 종료 절차를 따릅니다.


위 두 함수에는 좀더 볼 것이 있는데. 그것은 참조 카운터입니다.

socket로 소켓을 열면 참조 카운터가 1 증가 합니다.

그리고 다른 자식 프로세스로 복사될 때도 참조 카운터가 1증가 합니다.

close는 참조 카운터를 1감소 시킵니다. 그러다가 참조카운터가 0이 되면 소켓을 닫습니다.

소켓 참조 카운터가 0이 아니라면 그것은 열린 상태가 되는 것입니다.



int shutdown( int sockfd, int howto );


이 함수도 네트워크 연결을 종료시키는 데 사용합니다.

close()와 다른 점은 close는 참조 카운터를 1감소시키고 참조 카운터가 0이 되면 종료하는데

shutdown()은 참조 카운터와 상관없이 TCP의 연결 종료 절차를 시작합니다.

그런데 close()함수는 양방향(send recv) 둘 다 종료시키는데 반해,

shutdown함수는 howto인자에 따라 동작이 달라집니다.


위에서 close함수를 설명할 때 약점이 하나 있었습니다.

close()호출 후에 받을 데이터가 있다면 어떻게 할까요? 그건 받을 수 없습니다.

그러나 shutdown의 howto 인자를 설정하면 그것이 가능합니다.

그 값에는 다음과 같은 것이 있습니다.


SHUT_RD


연결의 recv 한쪽만 닫습니다. 이제 이 소켓으로는 데이터를 받을 수 없습니다.

그리고 recv buffer도 폐기됩니다.


SHUT_WR


연결의 send 한쪽만 닫습니다. 이제 이 소켓으로는 어떤 데이터도 보낼 수 없게 됩니다.

send buffer에 남아 있는 데이터는 모두 보낸 뒤에 TCP 연결 종료 절차가 뒤따릅니다.


SHUT_RDWR 


연결의 양쪽 다 닫습니다. 만약에 자신은 데이터를 다 보냈다 하면,

SHUT_WR인자를 설정하여 shutdown()을 호출하면

다른 쪽이 보내는 데이터를 받을 수 있게 되는 것입니다.