본문 바로가기

UNIX_LINUX_C_C++

Poll_thread 소켓

출처 : http://blog.naver.com/pigeonkim?Redirect=Log&logNo=140037278234

Poll함수를 이용하여 클라이언트 접속 여부만 확인하고 데이터 처리는 Thread에서 한다.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/poll.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>

#define BUFSIZE255

intnread;
intstate = 0;
char*Client_add;
charmsg[100];

socklen_t clilen;

intclnt_number = 0;
intclnt_sockfds[10];
pthread_mutex_t mutx;

structpollfd client[1];

void*clnt_connection(void *arg);
voidsend_message(char *message, int len, int client_sockfd);
intdate();
intclock();
voidwrite_log(char *msg);

/***************************************************************************************
*function name: main()
*---------------------------------------------------------------------------------------
*return value:
*---------------------------------------------------------------------------------------
*Detail: 소켓 초기화, Poll함수를 이용한 접속유무 확인, 쓰레드 생성
***************************************************************************************/
int main(int argc, char **argv)
{
int server_sockfd, client_sockfd, sockfd;
struct sockaddr_in clientaddr, serveraddr;
pthread_t thread;

if (argc != 2)
{
printf("Usage : [port]\n");
exit(0);
}

system("clear");
printf(" ==========================================================\n\n");
printf(" = POLL_THREAD SERVER START =\n\n");
printf(" ==========================================================\n\n");

if(pthread_mutex_init(&mutx, NULL))
{
perror("Mutex init error : ");
}

if ((server_sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket error : ");
exit(0);
}

bzero(&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons(atoi(argv[1]));

state = bind(server_sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
if (state == -1)
{
perror("bind error : ");
exit(0);
}

state = listen(server_sockfd, 10);
if (state == -1)
{
perror("listen error : ");
exit(0);
}

// pollfd 구조체에 소켓지시자를 할당한다.
// 소켓에 쓰기 events (POLLIN)에 대해서 반응하도록 세팅한다.
client[0].fd = server_sockfd;
client[0].events = POLLIN;

while(1)
{
nread = poll(client, 1, -1);

// 만약 POLLIN 이벤트에 대해서 되돌려준 이벤트가(revents) POLLIN 이라면 accept 후 쓰레드 생성한다.
if (client[0].revents & POLLIN)//새로운 클라이언트 연결
{
clilen=sizeof(clientaddr);
client_sockfd = accept(server_sockfd, (struct sockaddr *)&clientaddr, &clilen);
printf("Client Connect : [%s]\n", inet_ntoa(clientaddr.sin_addr));

if (nread <= 0)
{
continue;
}//if (nread <= 0)

pthread_mutex_lock(&mutx);
clnt_sockfds[clnt_number++] = client_sockfd;
pthread_mutex_unlock(&mutx);

sprintf(msg,"Client ID :[%d] [%d] [%d] [Connected]",client_sockfd ,date(),clock());
write_log(msg);

//쓰레스 생성
pthread_create(&thread, NULL, clnt_connection, (void*)client_sockfd);

}//if (client[0].revents & POLLIN)
}//while(1)
}

/***************************************************************************************
*function name: clnt_connection()
*---------------------------------------------------------------------------------------
*return value:
*---------------------------------------------------------------------------------------
*Detail: 생성된 쓰레드에서 종료시까지 데이터를 읽고 send_message()를 통하여
* 접속 클라이언트에게 전달.
***************************************************************************************/
void* clnt_connection(void *arg)
{
int client_sockfd = (int)arg;
int str_len = 0;
char buf[BUFSIZE];
int i;

//접속 종료시까지 기다리고 있다가 읽을 데이터가 있으면 데이터를 읽어온다.
while((str_len = read(client_sockfd, buf, sizeof(buf))) != 0)
{
//읽어온 데이터를 접속 클라이언트에 전달한다.
send_message(buf, str_len, client_sockfd);
}

clnt_number--;
pthread_mutex_unlock(&mutx);

close(client_sockfd);
printf("Client Close : [%d]\n", client_sockfd);
sprintf(msg,"Client ID :[%d] [%d] [%d] [DisConnected]",client_sockfd,date(),clock());
write_log(msg);

return;
}

/***************************************************************************************
*function name: send_message()
*---------------------------------------------------------------------------------------
*return value:
*---------------------------------------------------------------------------------------
*Detail: 접속된 클라이언트에게 데이터 전달.
***************************************************************************************/
void send_message(char *buf, int len, int client_sockfd)
{
pthread_mutex_lock(&mutx);

write(client_sockfd, buf, len);
printf("Client[%d] : [%s]\n", client_sockfd, buf);
sprintf(msg,"Client ID :[%d] [%d] [%d] [%s]",client_sockfd, date(), clock(), buf);
write_log(msg);


pthread_mutex_unlock(&mutx);
}

/***************************************************************************************
*function name: date()
*---------------------------------------------------------------------------------------
*return value:
*---------------------------------------------------------------------------------------
*Detail: 현재 로컬타임 정보를 얻어옴.
***************************************************************************************/
int date()
{
char _date[14];

time_t time_now;
struct tm *tm;
time(&time_now);

tm=localtime(&time_now);
sprintf(_date, "%4d%02d%02d",tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday);

return(atol(_date));
}

/***************************************************************************************
*function name: date()
*---------------------------------------------------------------------------------------
*return value:
*---------------------------------------------------------------------------------------
*Detail: 현재 로컬타임 정보를 얻어옴.
***************************************************************************************/
int clock()
{
char _clock[14];

time_t time_now;
struct tm *tm;
time(&time_now);

tm=localtime(&time_now);
sprintf(_clock, "%02d%02d%02d", tm->tm_hour, tm->tm_min, tm->tm_sec);

return(atol(_clock));
}

/***************************************************************************************
*function name: write_log()
*---------------------------------------------------------------------------------------
*return value:
*---------------------------------------------------------------------------------------
*Detail: ./log 폴더에 오늘 날짜 파일에 로그를 쌓는다.
***************************************************************************************/
void write_log(char *msg)
{
FILE *fp;
char file_name[12];

sprintf(file_name,"./[log]/%d",date());

fp = fopen(file_name, "a");
fprintf(fp,"[%s]\n",msg);

fclose(fp);

}

'UNIX_LINUX_C_C++' 카테고리의 다른 글

C에서 C++ 작성한 라이브러리를 사용하고자 한다면?  (0) 2011.10.16
bind error 방지 하기  (0) 2011.10.16
extern의 사용  (0) 2011.10.16
GDB를 이용한 디버깅  (0) 2011.10.16
gcc와 make 강좌  (0) 2011.10.16