ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • TCP/IP 소켓 프로그래밍 - 16장 : 입출력 스트림 분리
    네트워크 2024. 6. 26. 15:54


    16장

    16-1 입력 스트림과 출력 스트림의 분리

     

    입력과 출력을 위한 도구가 별도로 나뉘어 구분할 수 있으면,

    입출력 스트림이 분리되었다고 표현한다.

     

     

    앞서 공부한 입출력 스트림의 분리 방법 2가지는 아래와 같았다.

    • 입력, 출력에 사용되는 파일 디스크립터 구분 ( 10장 )
    • 읽기, 쓰기 모드에 따른 FILE 포인터 구분 ( 15장 )

     

    스트림 분리 방법 또는 목적에 따라 기대할 수 있는 장점이 달라진다.

    • 10장에서의 파일 디스크립터 구분 : 입력 상관없이 출력이 가능 ⇒ 속도 향상
    • 15장에서의 FILE 포인터 구분 : 입력버퍼와 출력버퍼를 구분해 버퍼링 기능 향상

     

    파일 포인터를 대상으로 Half-close를 진행할 때에는 파일 디스크립터와 달리 좀 더 주의해야 한다.

    (단순히 서버측에서 fclose함수로 writefp를 닫아버리는 것만으로는 원하는 결과를 얻지 못한다!)

     


    16-2 파일 디스크립터의 복사와 Half - close

     

    책의 예제에서 스트림 종료 시 ( “fclose(writefp)” ) half-close가 진행되지 않은 이유는

    FILE 포인터와 파일 디스크립터, 그리고 소켓의 관계를 살펴보면 알 수 있다.

     

     

    예제에서의 FILE 포인터들은 1개의 FD 를 기반으로 만들어졌다.

    ( FILE * readfp = fdopen ( sock, “r” ); FILE * writefp = fdopen( sock, “w”); )

     

    이때, fclose 함수로 FILE 포인터를 지우면, 파일 디스크립터도 종료되고, 소켓도 종료된다.

    이를 해결하는 방법은, 파일 포인터를 만들기 전에 파일 디스크립터를 복사해 하나 더 만드는 것이다.

    이렇게만 하면 될 수 있는 이유 중 하나로,

    소켓은 모든 파일 디스크립터가 소멸되어야 소멸되는 점을 들 수 있다.

     

     

    파일 디스크립터는 입력과 출력이 모두 가능하고, 때문에 하나라도 남아있으면

    상대 호스트로 EOF가 전송되지 않으며 파일 디스크립터를 이용하면 문제없이 송수신이 가능하다.

    (별도의 EOF 전송 코드가 필요하다. )

     

     

    이 때문에 EOF가 전송되는 half-close를 위해서는 shutdown 함수를 이용해주어야 한다.


    이제는, 파일 디스크립터를 복사하는 방법을 알아보자.

     

    fork 함수 호출 시 진행되는 파일 디스크립터(FD) 복사와 위에서 언급한 FD 복사에는 차이가 있다.

     

    fork 함수 호출로 인한 복사

    • 프로세스를 그대로 복사 → 한 프로세스에 원본과 복사본 FD 동시에 존재하지 않음.

     

    위에서 말한 복사

    • 프로세스 생성 x → 한 프로세스 내부에 원본과 복사본 FD 모두 존재.

     

    주의할 점은, 파일 디스크립터는 값이 중복될 수 없어서

    파일 디스크립터 정수값은 서로 다르다는 점이다.

     

    복사의 표현을 좀 더 정확히하면,

    "동일한 파일 또는 소켓을 가리키는 또 다른 파일 디스크립터의 생성"에 가깝다.

    파일 디스크립터 복사는 아래 두 함수 중 하나를 이용한다.

     

    #include <unistd.h>
    
    int dup(int fildes);
    int dup2(int fildes, int fildes2);
    
    // 성공 시 복사된 파일 디스크립터, 실패 시 -1 리턴
    // fildes2 : 만들어질 파일 디스크립터의 정수를 명시적으로 전달

     

    책의 예제 코드를 실행해보면 모든 파일 디스크립터(원본, 복사본)가 닫히기 전까지는 출력이 되다가, 다 닫힌 이후로는 더 이상 출력되지 않는다.

     

     

    아래는 예제코드 실행 결과이다. (궁금하면 책 따라 쳐보자. )

     

     

    마지막으로 파일 포인터를 이용해 스트림을 분리했을 때,

    파일 디스크립터 복사EOF를 날려주는 shutdown함수를 이용해

    아래와 같은 코드를 넣어주면 문제없이 half-close를 이룰 수 있다.

    ...
    readfp = fdopen(clnt_sock, "r");
    writefp = fdopen(dup(clnt_sock), "w");
    ...
    
    shutdown(fileno(writefp), SHUT_WR);
    fclose(writefp);
    ...
    fclose(readfp);
    ...

     

     

    위 코드를 바탕으로 한 마지막 예제를 실행한 결과는 아래와 같다.

     

    클라이언트로부터 마지막 메시지를 수신 받으며 종료되는 모습이다.



Designed by Tistory.