수업/Network Programming

[Network Programming] TCP 기반 Half-close

hw-ani 2023. 5. 28. 16:42

close()  closesocket() 함수의 기능

    - socket의 완전 소멸을 의미

    - socket이 소멸되므로 더 이상 입출력이 안됨

    - 더 이상 입력이 안되므로 상대방 상태에 상관없는 일방적 종료의 형태

    - 일방적 종료를 할 경우 상대 host에 송수신이 완료되지 않은 데이터가 있을 때 문제

    - 따라서 Half-close 기법을 사용해야 한다.

 

 

 

 


Half-close

close()나 closesocket()으로 입출력 스트림을 모두 닫는 것이 아니라, 출력 스트림만 닫는 것이다.

상대방도 보낼 데이터가 없어서 종료를 원하는지 모르기때문에 입력 스트림은 열어둔다.

이렇게 입력 스트림이나 출력 스트림 중 하나를 닫는 것을 Half-close라고 한다.

 

 

 

shutdown

#include <sys/socket.h>

int shutdown(int sock, int howto);

첫번째 인자로 half-close 대상 file descriptor를 전달한다.

두번째 인자로 해당 file descriptor의 어떤 stream을 닫을지 결정한다. 아래 상수가 올 수 있다.

    - SUHT_RD : 입력 스트림 종료

    - SUHT_WR : 출력 스트림 종료

    - SUHT_RDWR : 입출력 스트림 종료

 

성공 시 0, 실패 시 -1을 반환한다.

 

이렇게 shutdown 함수가 호출되면 상대방에겐 EOF가 간다고 강의 자료에 나와있는데,
종료 요청을 보내는 것이므로, flag로 FIN이 가고 응용계층으로 EOF 데이터가 간다는 의미인듯.

 

 

 

TCP Half-close Example

//server.c

while (1) {
    read_cnt = fread((void*)buf, 1, BUF_SIZE, fp);
    if (read_cnt < BUF_SIZE) {
        write(clnt_sd, buf, read_cnt);
        break;
    }
    write(clnt_sd, buf, BUF_SIZE);
}

shutdown(clnt_sd, SHUT_WR);   //출력 스트림만 close
read(clnt_sd, buf, BUF_SIZE);
printf("Message from client: %s\n", buf);

fclose(fp);
clsoe(clnt_sd);   //소켓 완전히 종료
close(serv_sd);
//client.c

while((read_cnt = read(sd, buf, BUF_SIZE)) != 0)
    fwrite((void*)buf, 1, read_cnt, fp);

puts("Received file data");
write(sd, "Thank you", 10);//server에서 연결 종료 요청 후 client에서 보내는 추가 데이터
fclose(fp);
close(sd);

 

 

교수님께 말씀하시길...
내가 안 보낼거라면 상대방이 보낼 데이터가 손실되든 말든 받을 필요도 없는 경우가 많아서,
최근 나온 protocol들은 이런 기능이 없다고 한다.