TCPIP Socket Programming 17 2 Khkimdblab hannam ac
TCP/IP Socket Programming… 제 17장 멀티쓰레드 기반의 서버구현 데이터베이스 실험실 석사 2학기 김기훈 Khkim@dblab. hannam. ac. kr HANNAM Univ.
TCP/IP Socket Programming… Network Lab. 쓰레드란 무엇인가[2] q 프로세스와 쓰레드 HANNAM Univ. 4
TCP/IP Socket Programming… Network Lab. 쓰레드 생성하기[2] q thread 1. c 실행결과 void *thread_function(void *arg); int main(int argc, char **argv){ int state; pthread_t t_id; void *t_return; state = pthread_create(&t_id, NULL, thread_function, NULL); if(state != 0){ puts("쓰레드 생성 오류"); exit(1); } printf("생성된 쓰레드 ID : %d n", t_id); sleep(3); puts("main함수 종료"); Process 쓰레드 생성 return 0; } void * thread_function(void *arg) { int i; for(i=0; i<3; i++){ sleep(2); puts("쓰레드 실행 중"); } } 종료 Thread 종료 HANNAM Univ. 6
TCP/IP Socket Programming… Network Lab. 쓰레드 생성하기[4] q thread 2. c int main(int argc, char **argv){. . . void *t_return; state = pthread_create(&t_id, NULL, thread_function, NULL); . . . 실행결과 printf("생성된 쓰레드 ID : %d n", t_id); /* 쓰레드 종료 시까지 main함수의 실행을 지연 */ state = pthread_join(t_id, &t_return); /* 리턴 값 저장 */ if(state !=0 ){ puts("쓰레드 Join 오류"); exit(1); } printf("main함수 종료, 쓰레드 리턴 %s", (char*)t_return); free(t_return); return 0; Process } void * thread_function(void *arg) { int i; char *p = (char*)malloc(20*sizeof(char)); strcpy(p, "쓰레드 종료됨 !n"); for(i=0; i<3; i++){ sleep(2); puts("쓰레드 실행 중"); } return p; } 쓰레드 생성 Thread JOIN 대기상태 RETURN 종료 종료 HANNAM Univ. 8
TCP/IP Socket Programming… Network Lab. 다중 쓰레드 생성하기[2] q Thread 3. c 실행결과 void *thread_summation(void *arg); int sum=0; int sum 1[]={1, 5}; int sum 2[]={6, 10}; int main(int argc, char **argv){ pthread_t id_t 1, id_t 2; void *t_return; pthread_create(&id_t 1, NULL, thread_summation, (void *)sum 1); pthread_create(&id_t 2, NULL, thread_summation, (void *)sum 2); /* 쓰레드 종료 시까지 main함수의 실행을 지연 */ pthread_join(id_t 1, &t_return); pthread_join(id_t 2, &t_return); printf("main함수 종료, sum = %d n", sum); return 0; Thread Process 쓰레드 생성 } void * thread_summation(void *arg){ RETURN } 종료 JOIN int start = ((int*)arg)[0]; int end = ((int*)arg)[1]; for(; start<=end; start++){ sum+=start; } Thread JOIN 종료 종료 HANNAM Univ. 10
TCP/IP Socket Programming… Network Lab. 다중 쓰레드 생성하기[3] q Thread 4. c #define NUMBER 10000 실행결과 void *thread_increment(void *arg); int num=0; int main(int argc, char **argv){ int i; pthread_t thread_id[10]; void *t_return; for(i=0; i<10; i++) pthread_create(&thread_id[i], NULL, thread_increment, NULL); /* 생성한 모든 쓰레드 종료 시까지 main 함수의 실행을 지연 */ for(i=0; i<10; i++) pthread_join(thread_id[i], &t_return); printf("main함수 종료, num=%d n", num); return 0; } void *thread_increment(void *arg){ int i; for(i=0; i<NUMBER; i++) num++; } HANNAM Univ. 11
TCP/IP Socket Programming… Network Lab. 임계영역 & 쓰레드의 문제점[1] q 컴퓨터가 덧셈하는 원리 int i = 10 int j = 20 j+=i HANNAM Univ. 12
TCP/IP Socket Programming… Network Lab. 임계영역 & 쓰레드의 문제점[2] q 두 개의 쓰레드에 의한 덧셈 원리 int i = 10. . . i+=10 HANNAM Univ. 13
TCP/IP Socket Programming… Network Lab. 뮤텍스(Mutex)[1] q 뮤텍스 Mutual Exclusion의 줄임말로 쓰레드들의 동시접근을 허용하지 않겠다는 의미 ■ Pthread_mutex_t 타입변수를 가르켜 흔히 뮤텍스라고 함 ■ q 뮤텍스의 기본원리 ■ ■ 임계영역에 들어갈 때 뮤텍스를 잠그고 들어감 임계영역을 빠져 나올 때 뮤텍스를 풀고 나옴 q 뮤텍스 조작함수 초기화 : pthread_mutex_init (pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr) ■ 잠금 : pthread_mutex_lock (pthread_mutex_t *mutex) ■ 잠금 해제 : pthread_mutex_unlock (pthread_mutex_t *mutex) ■ 소멸 : pthread_mutex_destroy (pthread_mutex_t *mutex) ■ HANNAM Univ. 15
TCP/IP Socket Programming… Network Lab. 뮤텍스(Mutex)[2] q 뮤텍스의 동기화 원리 2. Thread B 진입 Thread B pthread_mutex_lock 함 수 호출 후 임계영역에 진입 Thread A 임계영역 [1] 임계영역 [3] Thread B 진입 Thread A Pthread_mutux_lock 함 수 호출 후 대기상태 1. Pthread_mutex_unlock 함수 호출 후 임계 영역 탈출 Thread B 임계영역 [2] Thread A 진입상태 HANNAM Univ. 16
TCP/IP Socket Programming… Network Lab. 뮤텍스(Mutex)[3] q mutex. c void *thread_increment(void *arg); char thread 1[] = "A Thread"; char thread 2[] = "B Thread"; pthread_mutex_t mutx; int number = 0; int main(int argc, char **argv){ pthread_t t 1, t 2; void *thread_result; int state; state = pthread_mutex_init(&mutx, NULL); if(state){ puts("뮤텍스 초기화 실패"); exit(1); } pthread_create(&t 1, NULL, thread_increment, &thread 1); pthread_create(&t 2, NULL, thread_increment, &thread 2); pthread_join(t 1, &thread_result); pthread_join(t 2, &thread_result); printf("최종 number : %d n", number); pthread_mutex_destroy(&mutx); return 0; } void *thread_increment(void * arg) { int i; for(i=0; i<5; i++){ pthread_mutex_lock (&mutx); sleep(1); number++; printf ("실행 : %s, number : %d n", (char*)arg, number); pthread_mutex_unlock (&mutx); } } 실행결과 HANNAM Univ. 17
TCP/IP Socket Programming… Network Lab. 세마포어(Semaphore)[3] q semaphore. c void *thread_snd(void *arg); void *thread_rcv(void *arg); sem_t bin_sem; int number = 0; char thread 1[] = "A Thread"; char thread 2[] = "B Thread"; char thread 3[] = "C Thread"; void *thread_snd(void * arg){ int i; for(i=0; i<4; i++){ while(number != 0); sleep(1); number++; printf("실행 : %s, number : %d n", (char*)arg, number); sem_post(&bin_sem); } } int main(int argc, char **argv){ pthread_t t 1, t 2, t 3; void *thread_result; int state; state = sem_init(&bin_sem, 0, 0); //bin_sem은 0으로 설정 if(state != 0){ puts("세마포어 초기화 실패"); exit(1); } pthread_create(&t 1, NULL, thread_snd, &thread 1); pthread_create(&t 2, NULL, thread_rcv, &thread 2); pthread_create(&t 3, NULL, thread_rcv, &thread 3); pthread_join(t 1, &thread_result); pthread_join(t 2, &thread_result); pthread_join(t 3, &thread_result); printf("최종 number : %d n", number); sem_destroy(&bin_sem); return 0; void *thread_rcv(void * arg){ int i; for(i=0; i<2; i++){ sem_wait(&bin_sem); number--; printf("실행 : %s, number : %d n", (char*)arg, number); } 실행결과 } } HANNAM Univ. 20
TCP/IP Socket Programming… Network Lab. 세마포어(Semaphore)[4] q semaphore 2. c void *thread_snd(void *arg); void *thread_rcv(void *arg); sem_t bin_sem 2; int number = 0; char thread 1[] = "A Thread"; char thread 2[] = "B Thread"; char thread 3[] = "C Thread"; int main(int argc, char **argv){ pthread_t t 1, t 2, t 3; void *thread_result; int state; state = sem_init(&bin_sem, 0, 0); //bin_sem은 0으로 설정 if(state != 0){ puts("세마포어 초기화 실패"); exit(1); } pthread_create(&t 1, NULL, thread_snd, &thread 1); pthread_create(&t 2, NULL, thread_rcv, &thread 2); pthread_create(&t 3, NULL, thread_rcv, &thread 3); pthread_join(t 1, &thread_result); pthread_join(t 2, &thread_result); pthread_join(t 3, &thread_result); printf("최종 number : %d n", number); sem_destroy(&bin_sem); return 0; void *thread_snd(void * arg){ int i; for(i=0; i<4; i++){ number++; printf("실행 : %s, number : %d n", (char*)arg, number); sem_post(&bin_sem); sem_wait(&bin_sem 2); } } void *thread_rcv(void * arg){ int i; for(i=0; i<2; i++){ sem_wait(&bin_sem); number--; printf("실행 : %s, number : %d n", (char*)arg, number); sem_post(&bin_sem 2); } 실행결과 } } HANNAM Univ. 21
TCP/IP Socket Programming… Network Lab. 쓰레드 기반 서버 구현[1] q chat_server. c #define BUFSIZE 100 void *clnt_connection(void *arg); void send_message(char *message, int len); void error_handling(char * message); int clnt_number = 0; int clnt_socks[10]; pthread_mutex_t mutx; void *clnt_connection(void *arg){ int clnt_sock = (int)arg; int str_len = 0; char message[BUFSIZE]; int i; while((str_len = read(clnt_sock, message, sizeof(message))) != 0) send_message(message, str_len); pthread_mutex_lock(&mutx); int main(int argc, char **argv){ for(i=0; i<clnt_number; i++){ /*클라이언트 연결 종료 시 */ int serv_sock; if(clnt_sock == clnt_socks[i]){ int clnt_sock; for(; i<clnt_number-1; i++) struct sockaddr_in serv_addr; clnt_socks[i] = clnt_socks[i+1]; struct sockaddr_in clnt_addr; break; int clnt_addr_size; } pthread_t thread; }. . clnt_number--; while(1){ pthread_mutex_unlock(&mutx); clnt_addr_size = sizeof(clnt_addr); close(clnt_sock); clnt_sock = accept(serv_sock, (struct sockaddr*) &clnt_addr, return 0; & clnt_addr_size); } pthread_mutex_lock(&mutx); void send_message(char * message, int len){ clnt_socks[clnt_number++] = clnt_sock; int i; pthread_mutex_unlock(&mutx); pthread_mutex_lock(&mutx); pthread_create(&thread, NULL, clnt_connection, (void*)clnt_sock); for(i=0; i<clnt_number; i++) printf("새로운 연결, 클라이언트 ip : %s n", write(clnt_socks[i], message, len); inet_ntoa(clnt_addr. sin_addr)); pthread_mutex_unlock(&mutx); } } return 0; } HANNAM Univ. 22
TCP/IP Socket Programming… Network Lab. 쓰레드 기반 서버 구현[2] q chat_client. c void *send_message(void *arg){ /*메시지 전송 쓰레드 실행 함수*/ int sock = (int)arg; char name_message[NAMESIZE+BUFSIZE]; while(1){ fgets(message, BUFSIZE, stdin); if(!strcmp(message, "qn")){ /* 'q' 입력 시 종료 */ close(sock); exit(0); } int main(int argc, char **argv){ sprintf(name_message, "%s %s", name, message); int sock; write(sock, name_message, strlen(name_message)); struct sockaddr_in serv_addr; } pthread_t snd_thread, rcv_thread; } void *thread_result; void *recv_message(void *arg){. . int sock = (int)arg; sock=socket(PF_INET, SOCK_STREAM, 0); char name_message[NAMESIZE+BUFSIZE]; . . int str_len; while(1){ pthread_create(&snd_thread, NULL, send_message, (void*)sock); str_len = read(sock, name_message, NAMESIZE+BUFSIZE-1); pthread_create(&rcv_thread, NULL, recv_message, (void*)sock); if(str_len == -1) return 1; pthread_join(snd_thread, &thread_result); name_message[str_len] = 0; pthread_join(rcv_thread, &thread_result); fputs(name_message, stdout); close(sock); } return 0; } } #define BUFSIZE 100 #define NAMESIZE 20 void *send_message(void *arg); void *recv_message(void *arg); void error_handling(char * message); char name[NAMESIZE]="[Default]"; char message[BUFSIZE]; HANNAM Univ. 23
TCP/IP Socket Programming… Network Lab. 쓰레드 기반 서버 구현[3] q chat_server. c & chat_client. c 실행결과 server Client MR. Lee Client Thomas HANNAM Univ. 24
TCP/IP Socket Programming… Network Lab. 참고문헌 q “TCP/IP 소켓 프로그래밍”, 윤성우 저 q “운영체제(Understanding operating Systems)”, 김희철, 박영민, 이금석, 조병호, 최 의인 공역 HANNAM Univ. 25
TCP/IP Socket Programming… Network Lab. Q&A HANNAM Univ. 26
- Slides: 26