- 프로세스 기반의 분리 : write용 프로세스, read용 프로세스 fork를 통한 분리
- FILE 구조체 포인터 기반의 분리 : FILE 구조체를 각각 write와 read로 관리
- 입력모드과 출력모드의 구분을 통한 구현의 편의성 증대
- 입력 버퍼와 출력 버퍼를 구분함으로 인한 버퍼링 기능의 향상
readfp=fdopen(sock, "r");
writefp=fdopen(sock, "w");
- Half-close : EOF를 전달하여 더 이상 보낼 데이터가 없다고 알리고 출력 스트림을 닫아버림
- fclose를 통해 FILE* 를 닫으면 연결된 파일 디스크립터도 close가 되어버림
- write에 사용하고 있던 FILE*를 닫으면 read도 제대로 이루어지지 않음
int main(int argc, char *argv[])
{
FILE * readfp;
FILE * writefp;
...;
readfp=fdopen(sock, "r");
writefp=fdopen(sock, "w");
...;
fclose(writefp);
...;
fgets(buf, sizoef(buf), readfp);
fclose(readfp);
return 0;
}
서버가 마지막 문자열을 수신하지 못하는 상황
이 일어날 수 잇다.
int main(int argc, char *argv[])
{
int sock;
char message[BUF_SIZE];
int str_len;
struct sockaddr_in serv_adr;
FILE * readfp;
FILE * writefp;
sock=socket(PF_INET, SOCK_STREAM, 0);
...;
readfp=fdopen(sock, "r"); // fd -> FILE*
writefp=fdopen(sock, "w"); // fd -> FILE*
}
while(1)
{
fputs("Input message(Q to quit): ", stdout);
fgets(message, BUF_SIZE, stdin);
if(!strcmp(message,"q\n") || !strcmp(message,"Q\n")) {
break;
}
fputs(message, writefp); // 전송
fflush(writefp); // 버퍼 비움
fgets(message, BUF_SIZE, readfp); // 수신
printf("Message from server: %s", message);
}
fclose(writefp);
fclose(readfp);
return 0;
}
위 문제를 해결하기 위해서 파일 디스크립터를 복사하고 각각에 FILE*를 연결하면 소멸 시 해당 파일 디스크립터만 소멸
파일 디스크립터의 복사
동일한 파일 또는 소켓의 접근을 위한 또 다른 파일 디스크립터의 생성
dup은 복사된 파일 디스크립터 번호가 운영체제에서 주어진다면, dup2는 복사된 파일 디스크립터의 번호를 지정할 수 있다.
#include <unistd.h>
int dup(int fildes);
int dup2(int fildes, int fildes2);
// 성공 시 복사된 파일 디스크립터, 실패 시 -1 반환
// fildes : 복사할 파일 디스크립터 전달
// fildes2 : 명시적으로 지정할 파일 디스크립터의 정수 값 전달
int main(int argc, char *argv[])
{
int serv_sock, clnt_sock;
FILE * readfp;
FILE * writefp;
...;
serv_sock=socket(PF_INET, SOCK_STREAM, 0);
...;
readfp=fdopen(clnt_sock, "r");
writefp=fdopen(dup(clnt_sock), "w"); // fd 복사
fputs("FROM SERVER: Hi~ client? \n", writefp);
fputs("I love all of the world \n", writefp);
fputs("You are awesome! \n", writefp);
fflush(writefp);
shutdown(fileno(writefp), SHUT_WR); // half-close
fclose(writefp);
fgets(buf, sizeof(buf), readfp); fputs(buf, stdout);
fclose(readfp);
return 0;
}
복사된 파일 디스크립터의 수에 상관없이 EOF의 전송을 동반하는 Half-close를 진행하기 위해서는 shutdown 함수를 호출해야 한다.