본문 바로가기

다중 연결 허용 서버의 구현법 (socket programming)

반응형

다중 사용자의 connect 를 처리하기 위한 방법은 총 3가지의 방식으로 구분한다.

1. 유닉스 호환환경에서 제공하는 fork() 를 이용한 다중 프로세스
2. IO 멀티플렉싱을 이용한 다중 연결
3. 멀티 쓰레드를 이용한 다중 연결

3가지의 방법은 어떤 것이 좋다 나쁘다고 할 것이 아니고 적당한 상황하에서 적정한 기술을 이용하는 것이 관건이라고 할 수 있을 것이다.

1. fork() 이용 소스
[CODE] /** 멀티 프로세스를 이용한 에코 서버 프로그램 리눅스 환경하에서 컴파일 하세요. 출처 : 열혈강의 TCP/IP **/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <signal.h> #include <arpa/inet.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/socket.h> #define BUFFSIZE 30 void error_handling(const 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; struct sigaction act; int addr_size, str_len, state; pid_t pid; char message[BUFFSIZE]; 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); 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, &addr_size); if (clnt_sock == -1) continue; if ((pid ==fork()) == -1) {   close(clnt_sock);   continue; } else if (pid >0) {   puts("connection success");   close("clnt_sock");   continue; } else {   close(serv_sock);   while( (str_len = read(clnt_sock, message, BUFFSIZE)) != 0) {   write(clnt_sock, message, str_len);   write(1, message, str_len);   }   puts("connection closing");   close(clnt_sock);   exit(0); } } return 0; } void z_handler(int sig) { pid_t pid; int rtn; pid = waitpid(-1, &rtn, WNOHANG); printf("zombi process ID: %d\n", pid); printf("return data : %d\n", WEXITSTATUS(rtn)); } void error_handling(const char* message) { fputs(message, stderr); fputc('\n', stderr); exit(1); } [/CODE]

2. select 이용 소스
[CODE] /** IO 멀티플렉싱을 이용한 에코 서버 프로그램 리눅스 환경하에서 컴파일 하세요. 출처 : 열혈강의 TCP/IP **/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/time.h> #include <netinet/in.h> #define BUFFSIZE 100 void error_handling(const char* message); int main(int argc, char **argv) { int serv_sock; struct sockaddr_in serv_addr; fd_set reads, temps; int fd_max; char message[BUFFSIZE]; int str_len; struct timeval timeout; if (argc != 2) { printf("USAGE : %s <port>\n", argv[0]); exit(1); } serv_sock = socket(PF_INET, SOCK_STREAM, 0); 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))) error_handling("bind() error"); if (listen(serv_sock, 5) == -1) error_handling("listen() error"); FD_ZERO(&reads); FD_SET(serv_sock, &reads); fd_max = serv_sock; while (1) { int fd, str_len; int clnt_sock, clnt_len; struct sockaddr_in clnt_addr; temps = reads; timeout.tv_sec = 5; timeout.tv_usec = 0; if (select(fd_max + 1, &temps, 0, 0, &timeout) == -1)   error_handling("select() error"); for (fd = 0; fd < fd_max+1; fd++) {   if(fd == serv_sock) {   clnt_len = sizeof(clnt_addr);   clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_len);   FD_SET(clnt_sock, &reads);   if (fd_max < clnt_sock)   fd_max = clnt_sock;   printf("client connection : file descriptor %d\n", clnt_sock);   }   else {   str_len = read(fd, message, BUFFSIZE);   if (str_len == 0) {   FD_CLR(fd, &reads);   close(fd);   printf("client closing: file descriptor %d\n", fd);     }   else {   write(fd, message, str_len);   }   } } } } void error_handling(const char* message) { fputs(message, stderr); fputc('\n', stderr); exit(1); } [/CODE]

반응형

댓글


Copyright ⓒ SmartWeb All rights reserved.