이어서 멀티 쓰레드 채팅프로그램의 chat_server.c 입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | #include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<string.h> #include<arpa/inet.h> #include<sys/socket.h> #include<netinet/in.h> #include<pthread.h> #include<time.h> #define BUF_SIZE 100 #define MAX_CLNT 100 #define MAX_IP 30 void * handle_clnt(void *arg); void send_msg(char *msg, int len); void error_handling(char *msg); char* serverState(int count); void menu(char port[]); /****************************/ int clnt_cnt=0; int clnt_socks[MAX_CLNT]; pthread_mutex_t mutx; int main(int argc, char *argv[]) { int serv_sock, clnt_sock; struct sockaddr_in serv_adr, clnt_adr; int clnt_adr_sz; pthread_t t_id; /** time log **/ struct tm *t; time_t timer = time(NULL); t=localtime(&timer); if (argc != 2) { printf(" Usage : %s <port>\n", argv[0]); exit(1); } menu(argv[1]); pthread_mutex_init(&mutx, NULL); serv_sock=socket(PF_INET, SOCK_STREAM, 0); memset(&serv_adr, 0, sizeof(serv_adr)); serv_adr.sin_family=AF_INET; serv_adr.sin_addr.s_addr=htonl(INADDR_ANY); serv_adr.sin_port=htons(atoi(argv[1])); if (bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1) error_handling("bind() error"); if (listen(serv_sock, 5)==-1) error_handling("listen() error"); while(1) { t=localtime(&timer); clnt_adr_sz=sizeof(clnt_adr); clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_adr, &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(" Connceted client IP : %s ", inet_ntoa(clnt_adr.sin_addr)); printf("(%d-%d-%d %d:%d)\n", t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min); printf(" chatter (%d/100)\n", clnt_cnt); } 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); // remove disconnected client 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++) write(clnt_socks[i], msg, len); pthread_mutex_unlock(&mutx); } void error_handling(char *msg) { fputs(msg, stderr); fputc('\n', stderr); exit(1); } char* serverState(int count) { char* stateMsg = malloc(sizeof(char) * 20); strcpy(stateMsg ,"None"); if (count < 5) strcpy(stateMsg, "Good"); else strcpy(stateMsg, "Bad"); return stateMsg; } void menu(char port[]) { system("clear"); printf(" **** moon/sun chat server ****\n"); printf(" server port : %s\n", port); printf(" server state : %s\n", serverState(clnt_cnt)); printf(" max connection : %d\n", MAX_CLNT); printf(" **** Log ****\n\n"); } | cs |
서버를 오픈하면 기본적으로 다음과 같은 화면을 출력해줍니다.
테스트한 port는 9190이고 최대 접속인원은 100명으로 제한을 두었습니다.
이 부분은 필요에 따라 변경해 사용하시면 됩니다.
* linux에서 포트를 사용할 때 한번 사용한 포트는 보안문제 때문에 당분간 사용할 수 없다고 합니다.
서버를 오픈하실 때 마다 포트번호를 달리 하셔야 오류가 발생하지 않습니다.
log의 아래에는 접속한 클라이언트를 표시해 주는 부분입니다.
반응형
'C > 소켓프로그래밍' 카테고리의 다른 글
[소켓프로그래밍] 멀티쓰레드 채팅 프로그램 (Linux) -1 (4) | 2018.12.28 |
---|