Skip to content
 

리눅스 데몬 개발 4/8

지난 3장까지는 기초적인 함수와 개녕이였고 이번 장부터는 실질 서버의 모습을 소개합니다.

첨부된 소스는 최소한의 코딩으로 만든 서버로 클라이언트가 접속한뒤 문자열을 송신하면 클라이어트에 받은 문자갯수를 돌려주고 종료하는 프로그램입니다.

테스트를 위해서는 telnet 을 클라이언트로 이용하시면 됩니다.
서버 기동시 포트번호를 파라메터로 입력하시면 되는데 주의할점은 1024 이하의 번호를 쓰기 위해서는 root로 로그인되어야 하고 이후번호의 경우는 무관합니다. linux의 기본 보안 정책이고..

tcp 서버를 만들기 위해서 가장 기본적으로 사용하는 함수는
socket, bind, listen, accept, recv, send, close

클라이언트라면
socket, connect, send, recv, close

서버의 경우는 bind, listen, accept 가 추가됩니다.

socket은 통신을 하기 위한 핸들을 생성하는 함수입니다.
파일 오픈과 동일한 기능이라고 생각하면 됩니다.
실재로 socket에서 리턴된 핸들에다 read, write와 같은 파일 명령으로 데이타를 송수신하여도 동일한 결과로 동작하게 됩니다.
close를 이용하는 걸 봐도 같다는걸 알수 있습니다.

bind는 뭔가를 묶는다는 뜻이므로 해당 어드레스와 포트를 시스템에게 예약하는 명령어입니다.

listen은 클라이언트가 젒속하도록 대기상태로 만드는 것입니다.
실제로 listen 이후부터는 클라이언트가 접속이 가능합니다.

일반적으로 listen( s, 5 )라고 5라는 숫자가 있는 리눅스의 기본 queue의 갯수가 5입니다. 변경할 필요도 없으면 크게 한다고 해서 실제로 커지지도 않습니다. 큐의 개념은 accept 로 빼내기전에 버퍼링되는 커넥션이라고 생각하면 됩니다.

accept라는것을 접속대기중인 클라이언트를 실제로 프로그램과 접속을 시켜주는 명령어입니다. accept의 리턴값이 소켓이고 새로운 소켓번호를 통해서 접속된 클라이언트와 송수신을 하게 되는 것입니다.

이후는 recv, read, send, write의 함수를 이용해서 통신을 하면됩니다.

샘플소스는 무조건 클라이언트를 기다라다가 접속이후 문자열을 기다리다가 문자열이 들어오면 문자열을 출력한뒤 클라이언트로 해당 문자열의 길이를 반환하고 종료하는 프로그랭입니다.

실제로 서버라기 보다는 수신 대기프로그램 및 수신 테스트 프로그램이라고 생각하면 됩니다.

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h>  

#include <netdb.h> 
#include <sys/socket.h> 
#include <arpa/inet.h>  

int main( int argc, char *argv[] ) 
{ 
    if ( argc != 2 ) 
    { 
        printf( "Usage : %s port 
", argv[0] ); 
        return -1; 
    }  

    struct sockaddr_in  addr;  

    memset( &addr, 0, sizeof(addr) );  

    addr.sin_addr.s_addr = htonl( INADDR_ANY ); 
    addr.sin_port = htons( atoi( argv[1] ) );  

    int s = socket( AF_INET, SOCK_STREAM, 0 );  

    if ( !bind( s, (struct sockaddr *)&addr, sizeof(struct sockaddr_in) ) ) 
    { 
        if ( !listen( s, 5 ) ) 
        { 
            int S = accept( s, NULL, NULL );  

            if ( S != -1 ) 
            { 
                char buff[1024]; 
                int  size;  

                memset( buff, 0, sizeof(buff) ); 
                size = read( S, buff, sizeof(buff) );  

                printf( "Read : %s 
", buff );  

                sprintf( buff, "Read %d bytes 
", size ); 
                write( S, buff, strlen(buff) );  

                close( S ); 
                printf( "Disconnect 
" ); 
            } 
            else 
            { 
                printf( "accept error 
" ); 
            } 
        } 
        else 
        { 
            printf( "listen error 
" ); 
        } 
    } 
    else 
    { 
        printf( "bind error 
" ); 
    }  

    close( s );  

    return 0; 
}

Leave a Reply