메뉴

문서정보

2002년에 만들어진 문서다. 당시에는 inetd를 사용했는데, (2014년)지금은 xinetd방식을 사용하고 있다. 지금 상황에 맞게 문서를 업데이트 한다. -- 2011/06/23

목차

xinetd 기반 네트워크 프로그래밍

xinetd 와 stand alone 방식

일반적으로 네트워크 프로그램을 만든다고 하면, 독립된 소켓 서버 프로그램을 생각할거다 socket -> bind -> listen으로 소켓 대기열을 만들고, accept함수로 연결 소켓을 가져온다음 멀티 스레드 혹은 멀티 프로세스방식으로 클라이언트 데이터를 처리하는 방식이다.

소켓 생성에서 부터 데이터처리까지의 모든 기능을 혼자서 수행하는 네트워크 프로그램을 stand alone방식 프로그램이라고 한다. 이러한 방법외에 네트워크 부분을 다른 데몬 프로그램(xinetd)에 맡기는 방식도 있다. 여기에서는 xinetd를 이용해서 네트워크 프로그램을 만드는 방법을 살펴볼 것이다.

소켓 프로그램은 역할에 따라 크게 두 부분으로 나눌 수 있다.
  1. 통신 설정 : soket->bind->listen->accept 로 이어지는 부분으로 클라이언트의 연결을 맺는다. 이때 소켓(파일)이 만들어진다.
  2. read, write 로 이어지는 부분. 소켓에 데이터를 읽고/쓰는 부분
그렇다면 이런 생각을 해 볼 수도 있을거다. 클라이언트와의 연결을 처리하는 프로세스를 분리한다. 이 프로세스는 오로지 클라이언트 연결만을 처리한다. accept 함수로 클라이언트 연결이 만들어지면, 데이터를 처리할 프로그램을 호출한다. 데이터 처리 프로그램은 fork & exec 함수로 실행할 건데, 이때 dup2 함수를 이용해서 연결 소켓을 자식 프로세스의 표준입력으로 복사해서 넘겨준다. 이제 자식 프로세스는 표준입력을 이용해서 데이터를 읽고 쓰면 된다. 자세한 구현은 inet 데몬 방식의 프로그램 개발을 참고하자.

xinetd

리눅스는 이런 일을 하는 프로그램을 제공한다. 이 데몬 프로그램은 유저가 설장한 포트들에 대기하고 있다가 클라이언트가 연결하면, 연결 소켓을 외부 프로그램에 넘겨서 처리하도록 한다. 이 프로그램을 xinetd라고 한다.

xinetd가 작동하려면 두 가지 설정 요소를 가져한다. 기다릴 포트 번호와 각 포트 번호에 연결된 클라이언트 요청을 처리할 프로그램의 위치다.

xinetd의 설정파일은 /etc/xinetd.d디렉토리 밑에 두면 된다. 파일의 내용은 대략 다음과 같다. 서비스의 이름이 myecho 라면
# cat /etc/xinetd.d/myecho
service myecho
{
    type = UNLISTED
    disable         = no
    socket_type     = stream
    protocol        = tcp
    user            = root
    wait            = no
    server = /usr/local/bin/echo
    port = 12345
}                                                                               

xined 기반 프로그램 개발

이제 프로그램을 개발해야 겠죠. 프로그램의 이름은 myecho로 했다.
#include <fcntl.h>
#include <string.h>

int main(int argc, char **argv)
{
  char buf[1024];
  memset(buf, 0x00, 1024);
  read(0, buf, 1024);
  write(0, buf, strlen(buf));
}
프로그램은 아주 간단하다. 소켓을 만들고 기다리는 과정을 xinetd에 맡겼기 때문이다.

쉘 스크립트로도 만들 수 있다.
# cat myecho
#!/bin/sh
read input
echo $input
3줄로 끝.

xined 기반 프로그램 테스트

이제 테스트를 해보자.

위에서 만든 myecho 설정파일을 /etc/xinetd.d/ 에 복사를 하고. xinetd 데몬을 재 시작 한다.
# /etc/init.d/xinetd restart
 * Stopping internet superserver xinetd                                       [ OK ] 

netstat로 서비스가 잘 떳는지 확인해 보자.
# netstat -nap | grep xine
tcp     0      0 0.0.0.0:8888     0.0.0.0:*       LISTEN      16947/xinetd    

8888번 포트로 서비스가 떠 있다. 해당 포트를 기다리는 프로세스는 myecho가 아닌 xinetd 라는 점에 주목하자. telnet 프로그램으로 테스트를 했다.
# telnet 127.0.0.1 8888
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
hello world
hello world
Connection closed by foreign host.
# 

inetd 방식과 stand alone 방식중 어느걸 선택해야 하나

inetd

각각 적당한 용도가 있다. 일단 inetd 방식의 경우 코드를 단순하게 마들 수 있다. 단순한 만큼 견고한 프로그램을 만들 수 있다. 다중의 클라이언트를 처리하기 위해서 사용하는 fork, select, poll 등을 신경쓸필요도 없다.

inetd 방식은 telnet, ftp, pop 서비스와 같은 빈번한 요구가 발생하지 않거나, 일단 요청을 받아들이면 꽤 오랜시간 작업을 수행하는 서비스에 적당하다. 반면 http 서비스와 같이 초기 반응속도가 중요시하거나 매우 빈번한 요청이 일어나는 서비스에는 적당한 방법이 아니다.

그리고 에러를 표준출력할 수 없으므로 디버깅이 까다로와 질수 있다는 단점이 있다. 디버깅을 원한다면 에러로그를 파일로 저장하는 방법을 사용해야 할것이다.

=== inetd ==== stand alone 방식은 http와 같은 반응속도가 중요하거나, 매우 빈번한 요청이 일어나는 서비스에 적당하다.

예를들어 서버가 oracle 에 연결해서 데이타를 가져오는 일을한다고 했을때 inetd 방식을 사용하면 클라이언트의 연결이 들어올때 마다 oracle DB로의 연결을 수행해야 할것이다. stand alone 방식의 경우 최초에 한번만 oracle DB로 연결하고, 새로운 클라이언트가 연결되더라도 이미 연결된 oracle DB로 작업을 할수 있을것이다. 코드량이 많아지고, 신경써야할 부분들이 매우 많아지겠지만...