2016년 6월 15일 수요일

뇌자극 TCP_IP 프로그래밍 25강 요약

25강 인터넷 서비스 프로그램 개발

1) 리눅스 데몬 프로그램 

서버 프로그램은 사용자와 상호작용할 필요가 없다.
서버는 테스트를 위한 목적으로 실행할 때 제외하고는
사용자와 상호작용하지 않는 상태로 실행해야 한다.
그래야 실행환경이 보장된다.

리눅스는 상호작용하지 않는 상태로 백그라운드에서 실행되는 프로세스를 데몬 프로세스라고 한다.

데몬 프로세스는 일반적으로 os의 시작과 더불어 구동되고 특별한 일 없으면 os가 종료할 때 종료된다.

GUI와 CLI

상호 작용은 크게 두 가지 방식으로 이루어진다.

텍스트를 이용하는 방법 - CLI (Command Line Interface)
아이콘, 메뉴, 버튼, 이미지를 이용하는 방법 - GUI (Graphic User Interface)

데몬 프로세스가 되기에서는 3가지 조건을 만족시켜야 한다.

1) 부모 프로세스로부터 독립 시킨다. 
   자식 프로세스는 부모 프로세스로 부터 영향을 받는다.
   쉘을 종요하면 자식 프로세스까지 함께 종료된다.
   이를 막기 위해서 부모 프로세스로 부터 독립되어야 한다.

2) 표준 입출력과 표준 에러를 닫는다. 
   사용자와의 상호작용은 키보드와 모니터로 이루어지므로
   표준 입출력과 표준 에러를 닫아준다.

3) 새로운 세션을 만든다. 
   일반적으로 세션은 로그인과 함께 만들어지며 그룹을 포괄하는 상위 개념이다.
   데몬 프로세스는 모든 환경에서 독립되어야 하므로 새로운 세션을 가져야 한다.

부모 프로세스로부터 독립시키기

fork 함수를 호출해서 자식 프로세스를 만든 뒤 부모 프로세스를 종료하면 된다.

표준 입출력 닫기

close(0);
close(1);
close(2);

새로운 세션 만들기

#include <unistd.h>
pid_t setsid(void);

데몬 프로세스 만들기

1) 자식 프로세스를 만든 뒤, 부모 프로세스를 종료한다.
2) 자식 프로세스의 표준 입력/출력/에러를 닫는다.
3) setid 함수를 호출한다.

아주 간단한 데몬 생성 함수를 만들어보자.

void make_daemon()
{
  pit_t pid;
  pid = fork();  //자식 프로세스 만들기

  //부모 프로세스 종료하기
  if(pid < 0)
    exit(0);
  else if(pid != 0)
    exit(0);

  close(0);  //표준 입력 닫기
  close(1);  //표준 출력 닫기
  close(2);  //표준 에러 닫기

  setsid();  //새로운 세션 만들기 
}

데몬 프로세스와의 상호작용

데몬 프로세스는 사용자와 상호작용을 할 수 없다.
그러나 아래와 같은 정보를 확인 할 수 있어야 하기에 상호작용을 완전히 포기할 수는 없다.

1) 프로그램 활동 정보를 확인할 수 있어야 한다.
2) 프로그램 오류 정보를 확인할 수 있어야 한다.
3) 서버 작동 중에 정보를 확인하거나 직접 조작할 수 있어야 한다.

1번 2번은 로그 파일을 이용한다.
3번은 IPC를 이용해서 서버/클라이언트 방식으로 상호 작용한다.

포그라운드와 백그라운드

데몬 프로세스는 부모 프로세스에서 독립한 자식 프로세스다.
독립한 자식 프로세스는 전면에서 실행된다.
전면에서 실행되는 이 상태를 포그라운드 상태라고 한다.
이때 부모 프로세스는 멈춤 상태가 된다.
Ctrl + z 키를 누르면 포그라운드 상태의 프로세스가 중단되고
부모 프로세스가 실행되면서 프롬프트가 뜬다.
여기에 다시 bg 명령을 내리면 부모 프로세스도 실행 상태가 유지되면서
자식 프로세스도 백그라운드에서 실행된다.
백그라운드 프로세스는 터미널의 주도권이 없다.

백그라운드 프로세스는 fg 명령을 이용해서 포그라운드 상태로 전환할 수 있다.
쉘은 여러 프로세스를 백그라운드 상태로 동시에 실행할 수 있는데,
 jobs 명령어를 이용해서 백그라운드 상태에 있는 프로세스 목록을 확인할 수 있다.
프로그램이 처음부터 백그라운드 모드로 실행되도록 하려면
프로그램 마지막에 & 옵션을 추가해주면 된다.

./testjob1 & ./testjob2 & ./testjob3
jobs
[1]     실행중     ./testjob1 &
[2]-    실행중     ./testjob2 &
[3]+   실행중     ./testjob3
fg 1 //1번 프로세스(tsetjob1)가 포그라운드 상태가 된다.

2. 인터넷 서비스 데몬

서버는 클라이언트의 연결을 기다리는 영역과 클라이언트와 통신하는 영역으로 나눌 수 있다.

클라이언트의 연결을 기다리는 영역을 전문적으로 기다리는 프로그램을 만든다고 가정하면

1) 여러 포트에서 클라이언트를 기다린다.
2) 클라이언트 요청이 들어오면 자식 프로세스를 만든다.
3) 각 포트 번호에 연결된 프로그램을 execl 함수로 실행한다.
4) 소켓을 dup2 함수를 이용해서 실행할 프로그램의 표준입력으로 복사한다.
5) 표준 입력을 이용해서 클라이언트와 통신할 수 있게 된다.

dup, dup2 함수
파일 지정번호를 복사한다.

#include <unistd.h>

int dup(int oldfd);  //가장 작은 파일 지정번호로 복사한다. 
int dup2(int oldfd, int newfd);  //newfd가 이미 열려있는 파일지정 번호라면 닫은 다음 새로 만든다.

리눅스는 xinetd라는 시스템 프로그램을 제공한다. 인터넷 서비스 데몬이라고 부른다.
이 프로그램은 유저가 설정한 포트를 기다리다가 클라이언트가 연결하면 포트에 연결된 프로그램을 실행해서 클라이언트 요청을 처리한다.

xineted 설치법
sudo apt-get install xinetd

포트와 프로그램의 연결관계 및 통신 프로토콜의 정보를 담은 설정 파일이 필요하다.
/etc/xinetd.d 디렉토리 밑에 파일로 존재한다.
이들 파일은 하나의 서비스에 대응되며, 다음과 같은 내용을 포함한다.

service myecho
{
   disable = no //서비스의 활성활 여부(yes면 비활성화, no면 활성화)
   port = 3600  //대기 포트 번호
   type = UNLISTED //서버의 형식 (표준 형식 = INTERNAL, 비표준 형식 = UNLISTED)
   protocol = tcp //통신 프로토콜(tcp 또는 udp)
   socket_type = stream //프로토콜과 쌍으로 지정한다
   wait = no //no로 지정하면 instances에서 지정한 만큼의 클라이언트를 허용한다.
   user = root //연결된 클라이언트를 어떤 유저 권한으로 실행할지 지정
   instances = 5 //최대 동시 접속 클라이언트 수
   server = /usr/local/bin/echo_server_xinetd //호출할 프로그램 지정(완전 경로 사용)
}

xinetd 설정 파일을 수정한 후 xinetd를 재시작하면 적용된다.

/etc/init.d/xinetd restart

인터넷 서비스 데몬의 장단점

장점 - 안정된 서비스 가능
단점 - 고성능을 보장 못함

소스 코드 받기

댓글 없음:

댓글 쓰기