소켓프로그래밍에서 쓰레드에 대해 궁금한점 올립니다
글쓴이: 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. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.
댓글 달기