소켓프로그래밍에서 쓰레드에 대해 궁금한점 올립니다
글쓴이: ch0nn0m / 작성시간: 월, 2009/08/10 - 8:24오후
윤성우 저자의 소켓프로그래밍인데요...
쓰레드부분인데 이해가 안가는 부분을 주석처리 해놨습니다...부탁드릴게요..^^;
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <arpa/inet.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <pthread.h> #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; int main(int argc, char **argv) { int serv_sock; int clnt_sock; struct sockaddr_in serv_addr; struct sockaddr_in clnt_addr; int clnt_addr_size; pthread_t thread; if(argc!=2) { printf("Usage : %s <port>\n", argv[0]); exit(1); } if(pthread_mutex_init(&mutx, NULL)) error_handling("mutex init error"); 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){ clnt_addr_size=sizeof(clnt_addr); clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_addr,&clnt_addr_size); pthread_mutex_lock(&mutx); <span>// accept함수는 클라이언트가 접속할때마다 accept를 하여 파일디스크립터를 계속 생성하는 건가요??</span> clnt_socks[clnt_number++]=clnt_sock; pthread_mutex_unlock(&mutx); pthread_create(&thread, NULL, clnt_connection, (void*)clnt_sock); printf("새로운 연결, 클라이언트 IP : %s \n", inet_ntoa(clnt_addr.sin_addr)); } return 0; } 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); <span>//여기 밑에부분 clnt_number는 여기 clnt_connection함수안에는 없는 변수입니다...전역변수로 선언된 clnt_number인 0이 들어가야되는게 아닌가요?? 그렇다면 결과가 이상하지 않나요?? </span> for(i=0; i<clnt_number; i++){ if(clnt_sock == clnt_socks[i]){ for( ; i<clnt_number-1; i++) clnt_socks[i]=clnt_socks[i+1]; break; } } clnt_number--; pthread_mutex_unlock(&mutx); close(clnt_sock); return 0; } void send_message(char * message, int len) { int i; pthread_mutex_lock(&mutx); for(i=0; i<clnt_number; i++) write(clnt_socks[i], message, len); pthread_mutex_unlock(&mutx); } void error_handling(char *message) { fputs(message, stderr); fputc('\n', stderr); exit(1); }
2가지가 궁금합니다...위에 표시한대로...
accpet는 새로운 클라이언트가 접속할때마다 파일디스크립터가 생성되는건지...?
함수안에 없는 clnt_number를 불러오는데...전역변수인 0을 읽어오는게 아닌건지..??
0을 읽어오면 이상해지는거 아닌지요??
Forums:
스레드가 생성되는
스레드가 생성되는 시점에 전역변수의 값이 이미 증가되었습니다.
동기화도 뮤텍스로 하고 있구요.
천천히 살펴보시면 정상적으로 동작하는 코드입니다.
clnt_socks[clnt_number++]=
=========================
CharSyam ^^ --- 고운 하루
=========================
=========================
CharSyam ^^ --- 고운 하루
=========================
...
accept()는 운영체제가 제공하는 시스템호출입니다.
질문하신바대로 accept()는 매번 정상 리턴시(신규 클라이언트 접속시) 소켓을 하나 생성하여 그 소켓디스크립터를 리턴하게 되어 있습니다.
달리 말하자면, 소켓 디스크립터(파일 디스크립터)를 매 정상 리턴시마다 신규 생성합니다.
* 당연히, 비정상시(에러 또는 시그널발생시) -1을 리턴하므로 리턴값에 유의하여 프로그래밍이 필요합니다.
* 부가적으로, read(), write()도 마찬가지로 리턴값에 유의하셔야 합니다.
------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.
------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.
댓글 달기