본문 바로가기

Etc/TCP/IP

프로세스 기반에 다중 접속 에코 서버

프로세스 기반에 다중 접속 에코 서버


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>

#define BUFSIZE 30


void error_handling(char *message);
void z_handler(int sig);

int main(int argc, char *argv[])
{
    int serv_sock;
    int clnt_sock;
    struct sockaddr_in serv_addr;
    struct sockaddr_in clnt_addr;

    // for signal
    struct sigaction act;
    int addr_size, str_len, state;
    
    // process id
    pid_t pid;
    char message[BUFSIZE];

    if(argc!=2)
    {
        printf("Usage : %s <port>\n", argv[0]);
        exit(1);
    }

    act.sa_handler = z_handler;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;

    state = sigaction(SIGCHLD, &act, 0); // signal handler register
    if(state != 0)
    {
        puts("sigaction() error!");
        exit(1);
    }

    serv_sock = socket(PF_INET, SOCK_STREAM, 0);
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family=AF_INET;
    serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    serv_addr.sin_port=htons(atoi(argv[1]));

    if(bind(serv_sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1)
        error_handling("bind() error");

    if(listen(serv_sock, 5) == -1)
        error_handling("listen error");

    while(1)
    {
        addr_size = sizeof(clnt_addr);
        clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);
        if(clnt_sock == -1) continue;

        // client 와 connect를 independent 적으로 생성
        if((pid = fork()) == -1) // fork fail
        {
            close(clnt_sock);
            continue;
        }
        else if(pid > 0)        // parent process
        {
            puts("create connection");
            close(clnt_sock);
            continue;
        }
        else                    // child process
        {
            close(serv_sock);

            // child process 의 처리 영역 : data receve and transfer
            while((str_len = read(clnt_sock, message, BUFSIZE)) != 0)
            {
                write(clnt_sock, message, str_len);
                write(1, message, str_len);
            }
            puts("close connnection");
            close(clnt_sock);
            exit(0);
        }
    }

    return 0;
}

void z_handler(int sig)
{
    pid_t pid;
    int rtn;

    pid = waitpid(-1, &rtn, WNOHANG);
    printf("소멸된 zombie process ID : %d \n", pid);
    printf("return data : %d \n\n", WEXITSTATUS(rtn));
}

void error_handling(char *message)
{
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}

'Etc > TCP/IP' 카테고리의 다른 글

프로세스간 통신 IPC (Inter-Process Communication)  (0) 2013.09.25
입출력 분할한 에코 서버  (0) 2013.09.25
Nagle 알고리즘  (0) 2013.09.25
TIME WAIT STATUS  (0) 2013.09.25
ip 주소를 이용해서 도메인 이름 알아내기  (0) 2013.09.25