네트워크 프로그래밍 -PIPE
what ?
파이프란?
운영체제가 제공하는 프로세스간 통신 채널로 일반 파일과 달리 메모리에 저장되지 않고 운영체제가 관리하는 임시파일로 데이터 저장이 아닌 데이터 전달용으로 사용된다.
how?
어떻게 동작?
1. 송신측(송신 프로세스)
파이프에 데이터를 씀
2. 수신측(수신프로세스)
파이프에서 데이터를 읽음
3. 파이프는 스트림채널을 제공 ( 송신된 데이터으 바이트 순서유지 - 그대로 읽기 가능)
=> TCP연결이 원격 프로세스 간에 스트림 채널을 제공한다면 파이프는 같은 컴퓨터 내의 프로세스 간에 스트림 채널을 제공
4.pipe()사용
-pipe를 사용하기 위해 두 개의 파일 디스크립터가 생성되어 하나는 쓰기용, 다른 파일 하나는 읽기를 함으로써 프로세스 사이에서 메시지를 전달 할 수 있게 됨
-단방향 스트림 채널만 제공
why?
왜 사용하나?
멀티프로세스 형태로 서버를 구현할 경우, 프로세스 사이에 데이터를 주고받을 필요가 있으며 이를 위해 프로세스간 통신 IPC(Inter Process Communication)가 사용됨
1. pipe() 생성 문법
#include <unistd.h>
int pipe(int fd[2]); // fd[0] : 수신용 파일디스크립터 저장, fd[1] : 송신용 파일디스크립터 저장
2. fork()를 호출
- fork()를 통해 자식프로세스와 부모프로세스간 읽고 쓰기를 pipe()를 통해서 사용
- fork() 호출시 생성되는 자식프로세스와 부모프로세스 모두 송수신용 프로세스를 사용할 수 있지만 단방향 통신일 경우 부모에서 자식 프로세스 혹은 자식에서 부모프로세스로 데이터를 보내는 경우에 보내는 쪽은 fd[0]만 사용하고 받는 쪽은 fd[1]만 사용 [ pipe는 단방향 스트림 채널만 제공함]
//부모프로세스가 자식프로세스로 데이터를 보내는 경우
int fd[2];
pid_t pid;
pipe(fd);
if((pid=fork())<0){ exit(0); } //자식프로세스를 생성
else if(pid>0){ close(fd[0]);}//부모 프로세스에서는 읽기용 파일 디스크립터를 제거
else if(pid==0){close(fd[1]);}//자식프로세스에서는 쓰기용 파일 디스크립터를 제거
3. 파이프를 활용한 에코 서버/클라이언트 프로그램
3.1 에코 서버 프로그램
- UDP형 에코 서버프로그램 작성
- 과정 : 클라이언트 -> 파이프에 메세지 작성[쓰기 : 부모프로세스] -> 파이프 메세지를 에코[읽기 : 자식프로세스] -> 클라이언트가 받음
- 부모가 자식 프로세스에 파이프를 통해 전달해 줄 데이터의 구조체
typedef struct mesg{
struct sockaddr_in addr;//클라이언트 주소
char data[MAX_BUFSZ];//에코할 데이터}mesg_t;
3.2 에코 클라이언트 프로그램
-과정 : UDP소켓 개설 후 키보드 입력을 통해 sendto()사용, 서버로부터 받은 메세지를 recvform()을 통해 수신해 화면에 출력
3.3 우분투를 활용한 UDP소켓통신프로그램 -> PIPE활용
[code요약]
server에서 pipe()를 구현하며 fork()를 활용해 부모프로세스를 통해 메세지를 recvfrom()하여 읽어들이고 pipe의 디스크립터가 저장된 pipefd[1]만 사용하여 자식 프로세스에 전송/ 자식프로세스는 pipe의 디스크립터가 저장된 pipefd[0]만 사용하여 부모 프로세스로부터 메세지를 읽어오고 메세지를 sendto()를 통해서 client로 전송하는 코드를 작성



pipe의 한계
pipe는 부모와 자식관계에 있는 프로세스간의 통신에서만 사용할 수 있기에 한계를 가지고 있음.
=> 극복하기 위한 방안 : FIFO(파이프에 이름을 부여해 가족관계가 아니더라도 임의의 다른 프로세스에서 이름을 통해 파이프에 접근할 수 있도록 한 방법)을 사용함. *FIFO혹은 named pipe라고 함