void * handle_clnt(void * arg); //핸들 클라이언트 함수 선언 void send_msg(char * msg, int len); //센드 메시지 함수 선언 void error_handling(char * msg); //에러핸들링 함수 선언
int clnt_cnt=0; //클라이언트 전역 변수 초기화 int clnt_socks{MAX_CLNT]; //클라이언트 소켓 배열 선언 pthread_mutex_t mutx; //뮤텍스 참조값 저장을 위한 변수 선언
int main(int argc, char *argv[]){ //메인 함수 int serv_sock, clnt_sock, clnt_adr_sz; //변수 선언 struct sockaddr_in serv_addr, clnt_addr; //소켓 구조체 선언 pthread_t t_id; if(argc!=2){ //포트 입력 확인 printf("Usage : $s <port>\n", argv[0]); exit(1); }
pthread_mutex_init(&mutx, NULL); //뮤텍스 생성 serv_sock=socket(PF_INET, SOCK_STREAM, 0); //IPv4 연결지향형 소켓 생성 if(serv_sock == -1) //소켓 미생성 시 에러 출력 error_handling("socket() error");
memset(&serv_addr, 0, sizeof(serv_addr)); //소켓 정보 초기화 serv_addr.sin_family=AF_INET; //IPv4 사용 serv_addr.sin_addr.s_addr=htonl(INADDR_ANY); //컴퓨터 IP를 반환 받아 입력 serv_addr.sin_port=htons(atoi(argv[1])); //포트 입력
if(bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr))==-1) //바인딩으로 IP와 포트 할당 error_handling("bind() error");
if(listen(serv_sock, 5)==-1) //소켓 연결요청 가능 상태로 설정 error_handling("listen() error");
while(1){ clnt_adr_sz=sizeof(clnt_addr); clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_adr_sz);//클라이언트 접속 대기
pthread_mutex_lock(&mutx); //임계영역 시작 clnt_socks[clnt_cnt++]=clnt_sock; //새 연결정보 등록 pthread_mutex_unlock(&mutx); //임계영역 끝
pthread_create(&t_id, NULL, handle_clnt, (void*)&clnt_sock); //쓰레드 생성 및 함수 실행 pthread_detach(t_id); //쓰레드 메모리 소멸 printf("Connected client IP : %s \n", inet_ntoa(clnt_addr.sin_addr)); //접속 클라이언트 IP 출력 } close(serv_sock); //서버 소켓 종료 return 0; }
void * handle_clnt(void * arg){ //핸들 클라이언트 함수 int clnt_sock=*((int*)arg); //입력 받은 소켓 대입 int str_len=0, i; //변수 선언 char msg[BUF_SIZE]; //메시지 배열 선언
while ((str_len=read(clnt_sock, msg, sizeof(msg)))!=0) //메시지 수신 send_msg(msg, str_len); //센드 메시지 함수 호출
pthread_mutex_lock(&mutx); //임계영역 시작 for(i=0); i<clnt_cnt; i++){ //연결 종료 클라이언트 제거 if(clnt_sock==clnt_socks[i]){ while(i++<clnt_cnt-1) clnt_socks[i]=clnt_socks[i+1]; break; } } clnt_cnt--; pthread_mutex_unlock(&mutx); //임계영역 끝 close(clnt_sock); //클라이언트 소켓 종료 return NULL; } void send_msg(char * msg, int len){ // 센드 메시지 함수 int i //변수 선언 pthread_mutex_lock(&mutx); //임계영역 시작 for(i=0; i<clnt_cnt; i++) //클라이언트 소켓에 메시지 출력 white(clnt_socks[i], msg, len); pthread_mutex_unlock(&mutx); //임계영역 끝 } void error_handling(char * msg){ //에러핸들링 함수 fputs(msg, stderr); fputc('\n', stderr); exit(1); }