다중 사용자의 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]
'유용한정보' 카테고리의 다른 글
모바일웹에서 자주 쓰는 속성들 (0) | 2014.04.15 |
---|---|
<![CDATA[ ]]> 이 구문은 무엇을 뜻하는 것일까요? (0) | 2014.04.11 |
JW 플레이어 기본태그 (0) | 2014.03.30 |
Flash Action script (0) | 2014.03.27 |
홈페이지 로봇 설정 방법 (0) | 2014.03.26 |
간단한 명령어로 좀비 PC 확인하기 (0) | 2014.03.26 |
구글 애드센스(Adsense) 728x90 크기 광고를 블로그 상단에 배치하면서 느낌점 (애드센스 광고수익을 높이기 위한 전략) (0) | 2013.12.30 |
티스토리 블로그 본문 상단에 애드센스 광고 배치 방법 (왼쪽, 오른쪽, 양쪽에 광고 배치하는 HTML코드) (0) | 2013.12.30 |
댓글