제 16장 입력과 출력 스트림의 완벽 분리 TCP/IP Socket Programming… 데이터베이스 실험실 박사 2학기 장창복
스트림의 분리 스트림(Stream) 스트림을 분리하는 이유는 무엇인가? 스트림을 분리했을 경우 발생하는 문제점 데이터가 이동하는 흐름 파일로부터 데이터를 송수신하기 위해 놓여진 “일종의 다리” 스트림을 분리하는 이유는 무엇인가? 소켓을 생성할 때 리턴되는 파일 디스크립터를 이용 입력, 출력, 입출력 겸용 스트림을 생성할 수 있음 입력, 출력 스트림의 분리 구현이 쉽고 전체적인 성능 향상을 기대할 수 있음 입출력 겸용 스트림의 생성 입출력 전환시 버퍼를 비워주는 작업 필요 스트림을 분리했을 경우 발생하는 문제점 EOF 메시지를 전송해 줘야 하는 상황 입력과 출력용 파일 포인터가 각각 존재하므로, 출력용 파일 포인터를 이용해서 fclose함수를 호출 문제 발생
스트림의 분리 서버 코드(exam7) int serv_sock; int clnt_sock; FILE* rstrm; FILE* wstrm; … serv_sock=socket(PF_INET, SOCK_STEAM,0); clnt_sock=accept(serv_sock,(struct sockaddr*)&clnt_addr,&clnt_addr_size); rstrm=fdopen(clnt_sock,”r”); wstrm=fdopen(clnt_sock,”w”); fputs(“FROM SERVER : Hello?\n”,wstrm); fputs(“I like network programming\n”,wstrm); fputs(“I like socket programming\n”,wstrm); fflush(wstrm); fclose(wstrm); fgets(buf, sizeof(buf), rstrm); fputs(buf,stdout); fclose(rstrm);
스트림의 분리 클라이언트 코드(exam8) int sock; FILE* rstrm; FILE* wstrm; … sock=socket(PF_INET, SOCK_STEAM,0); rstrm=fdopen(sock,”r”); wstrm=fdopen(sock,”w”); while(1) { if(fgets(buf, sizeof(buf), rstrm) == null) break; fputs(buf, stdout); fflush(stdout); } fputs(“From CLIENT : Thank you!\n”, wstrm); fflush(wstrm); fclose(writeFP); fclose(readFP);
스트림의 분리 exam7, exam8 파일 실행 예
스트림의 분리 서버 클라이언트 연결요청 EOF 메시지 1(FROM SERVER : Hello?\n) 메시지 2(I like network programming\n) 메시지 3(I like socket programming\n) EOF 메시지4(From CLIENT : Thank you!) 전달 되지 않음
파일 디스크립터의 복사와 스트림의 분리 스트림 종료 시의 문제점과 해결방안 입력용 파일 포인터와 출력용 파일 포인터 하나의 파일 디스크립터를 기반으로 생성 fclose함수 호출시 어떠한 파일 포인터를 인자로 전달하더라도, 파일 디스크립터의 종료와 동시에 소켓도 종료됨 FILE * File Descriptor SOCKET 1. fclose 2. File Descriptor 종료 3. SOCKET 종료
파일 디스크립터의 복사와 스트림의 분리 Half-close 방법 fdopen(fd, “r”) 파일 포인터(입력) 하나의 파일 디스크립터를 복사하여 두개로 만들고 가각의 디스크립터를 기반으로 파일 포인터를 획득 하나의 소켓에 접근할 수 있는 파일 디스크립터가 두 개 이상인 경우 모든 파일 디스크립터가 종료되어야만 해당 소켓이 종료됨 fdopen(fd, “r”) 파일 포인터(입력) 파일 디스크립터 파일 디스크립터 복사 SOCKET 파일 포인터(입력) 파일 디스크립터 fdopen(fd, “w”)
파일 디스크립터의 복사와 스트림의 분리 파일 디스크립터 복사하기 파일 디스크립터의 복사 디스크립터 복사 함수 파일에 접근할 수 있는 파일 디스크립터 정수 하나를 더 만들어 내는 것을 의미함 디스크립터 복사 함수 int dup(int fildes); int dup2(int fildes, int fildes2) fildes: 복사하고자 원하는 파일 디스크립터 fildes2: dup2 함수에서 복사되는 파일 디스크립터의 값을 명시적으로 지정
파일 디스크립터의 복사와 스트림의 분리 파일 디스크립터 복사 후 스트림 생성하기(exam9) int serv_sock; int clnt_sock; FILE* rstrm; FILE* wstrm; … serv_sock=socket(PF_INET, SOCK_STEAM,0); clnt_sock=accept(serv_sock,(struct sockaddr*)&clnt_addr,&clnt_addr_size); rstrm=fdopen(clnt_sock,”r”); wstrm=fdopen(dup(clnt_sock),”w”); fputs(“FROM SERVER : Hello?\n”,wstrm); fputs(“I like network programming\n”,wstrm); fputs(“I like socket programming\n”,wstrm); fflush(wstrm); fclose(wstrm); fgets(buf, sizeof(buf), rstrm); fputs(buf,stdout); fclose(rstrm);
파일 디스크립터의 복사와 스트림의 분리 exam8, exam9 파일 실행 예
Q & A