Toby's Study Blog
article thumbnail

1. ๐Ÿ“ฌ ์†Œ์ผ“ ํ†ต์‹  ์ด๋ž€??

์•„๋ž˜ ๊ธ€์—์„œ ์ •๋ฆฌํ•˜์˜€์Šต๋‹ˆ๋‹ค.

https://toby12.tistory.com/52

 

[ubuntu] ์†Œ์ผ“ ํ†ต์‹  ๋ฐ์ดํ„ฐ ์ „์†ก ๋ฐ ์ €์žฅ

์†Œ์ผ“ ํ†ต์‹ ์ด๋ž€? ์šฐ์„  ์†Œ์ผ“์€ ๋‘ ๊ฐœ์˜ ์ปดํ“จํ„ฐ(์—”๋“œํฌ์ธํŠธ)๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š” ํ†ต๋กœ๋ฅผ ์˜๋ฏธํ•˜๋ฉฐ ๋‘ ๊ฐœ์˜ ์ปดํ“จํ„ฐ๋Š” ์ด๋ฅผ ํ†ตํ•ด ๋„คํŠธ์›Œํฌ๊ฐ€ ํ˜•์„ฑ๋œ๋‹ค. ์œ„ ์ƒํƒœ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ  ๋ฐ›๋Š” ํ†ต์‹ ์„ ํ•˜๋Š” ๊ฒƒ์„ ์†Œ

toby12.tistory.com

 

2. ๐Ÿ“ฌ ์‹ค์Šต ๋ชฉํ‘œ

1. ์†Œ์ผ“ ํ†ต์‹ ์„ ์ด์šฉํ•œ ์ฑ„ํŒ… ํ”„๋กœ๊ทธ๋žจ ์ž‘์„ฑ

 

โ€ป ์ฑ„ํŒ… ์„œ๋ฒ„ โ€ป  

  1. ์„œ๋ฒ„ ์ดˆ๊ธฐํ™” ๋ฐ ์†Œ์ผ“ ์ƒ์„ฑ
    • ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์€ ํฌํŠธ ๋ฒˆํ˜ธ๋กœ ์„œ๋ฒ„ ์ดˆ๊ธฐํ™” ๋ฐ ์†Œ์ผ“์„ ์ƒ์„ฑ 
  2. ํด๋ผ์ด์–ธํŠธ ์—ฐ๊ฒฐ ๋Œ€๊ธฐ ๋ฐ ์ธ์ฆ
    • accept ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์—ฐ๊ฒฐ ์š”์ฒญ๋ฐ›์€ ํด๋ผ์ด์–ธํŠธ์˜ ์—ฐ๊ฒฐ 
    • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์—ฐ๊ฒฐ๋˜๋ฉด, ID ๋ฐ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๋ฐ›์•„ ์ธ์ฆ ์ˆ˜ํ–‰
  3. ํด๋ผ์ด์–ธํŠธ ๊ด€๋ฆฌ ๋ฐ ์“ฐ๋ ˆ๋“œ ์ƒ์„ฑ
    • ์ตœ๋Œ€ MAX_CLNT ๊ฐœ์ˆ˜๊นŒ์ง€์˜ ํด๋ผ์ด์–ธํŠธ๋ฅผ ๊ด€๋ฆฌ
    • ์ƒˆ๋กœ์šด ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์—ฐ๊ฒฐ๋˜๋ฉด, ์“ฐ๋ ˆ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ํ•ด๋‹น ํด๋ผ์ด์–ธํŠธ์™€ ํ†ต์‹ ์„ ๋‹ด๋‹น
  4. ๋ฉ”์‹œ์ง€ ์ „์†ก
    • send_msg ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†ก
    • 'ALLMSG'๋ผ๋Š” ํŠน๋ณ„ํ•œ ์ˆ˜์‹ ์ž์—๊ฒŒ๋Š” ๋ชจ๋“  ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†ก
    • 'IDLIST' ์ˆ˜์‹ ์ž์—๊ฒŒ๋Š” ํ˜„์žฌ ์„œ๋ฒ„์— ์—ฐ๊ฒฐ๋œ ๋ชจ๋“  ํด๋ผ์ด์–ธํŠธ์˜ ID ๋ชฉ๋ก์„ ์ „์†ก
  5. ์“ฐ๋ ˆ๋“œ ํ•จ์ˆ˜ (clnt_connection)
    • ํด๋ผ์ด์–ธํŠธ ์“ฐ๋ ˆ๋“œ ํ•จ์ˆ˜๋กœ, ํด๋ผ์ด์–ธํŠธ์™€์˜ ํ†ต์‹ ์„ ๋‹ด๋‹น
    • ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜์‹ ํ•˜๊ณ , ์ด๋ฅผ ์ฒ˜๋ฆฌํ•˜์—ฌ ๋‹ค๋ฅธ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์ „ํŒŒ

โ€ป ํด๋ผ์ด์–ธํŠธ โ€ป  

  1. ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™” ๋ฐ ์†Œ์ผ“ ์ƒ์„ฑ
    • ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์€ ์„œ๋ฒ„์˜ IP ์ฃผ์†Œ์™€ ํฌํŠธ ๋ฒˆํ˜ธ๋กœ ์„œ๋ฒ„์— ์†Œ์ผ“์„ ์ƒ์„ฑํ•˜์—ฌ ์—ฐ๊ฒฐ์„ ์‹œ๋„
  2. ์ธ์ฆ
    • ๋งค๊ฐœ๋ณ€์ˆ˜์— ์ง€์ •ํ•œ ์ด๋ฆ„์œผ๋กœ ์„œ๋ฒ„์— ์ ‘์†, ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ํ•จ๊ป˜ ์ „์†กํ•˜์—ฌ ์ธ์ฆ์„ ์ˆ˜ํ–‰ํ•จ
  3. ๋ฉ”์‹œ์ง€ ์†ก์ˆ˜์‹ 
    • ์‚ฌ์šฉ์ž๋Š” ํ‚ค๋ณด๋“œ๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ์ž…๋ ฅํ•˜๊ณ , ์ด๋ฅผ ์„œ๋ฒ„์— ์ „์†ก
    • ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ์˜ ๋ฉ”์‹œ์ง€๋Š” ๋ณ„๋„์˜ ์“ฐ๋ ˆ๋“œ๋ฅผ ํ†ตํ•ด ์ˆ˜์‹ ๋˜์–ด ํ™”๋ฉด์— ์ถœ๋ ฅ๋จ
  4. ์“ฐ๋ ˆ๋“œ ํ•จ์ˆ˜ (send_msg, recv_msg)
    • ๊ฐ๊ฐ ๋ฉ”์‹œ์ง€ ์†ก์‹  ๋ฐ ์ˆ˜์‹ ์„ ๋‹ด๋‹นํ•˜๋Š” ์“ฐ๋ ˆ๋“œ ํ•จ์ˆ˜์ด๋‹ค. 
    • send_msg ํ•จ์ˆ˜๋Š” ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ์„ ์ฝ์–ด ์„œ๋ฒ„๋กœ ์ „์†กํ•˜๊ณ 
    • recv_msg ํ•จ์ˆ˜๋Š” ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ์˜ ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜์‹ ํ•˜์—ฌ ํ™”๋ฉด์— ์ถœ๋ ฅํ—˜

โ€ป ์ถ”๊ฐ€ ๋‚ด์šฉ โ€ป 

  • ์“ฐ๋ ˆ๋“œ ์‚ฌ์šฉ
    • ๊ฐ ํด๋ผ์ด์–ธํŠธ๋Š” ๋ณ„๋„์˜ ์“ฐ๋ ˆ๋“œ์—์„œ ์ฒ˜๋ฆฌ๋˜๊ณ  ์ด๋ฅผ ํ†ตํ•ด ์—ฌ๋Ÿฌ ํด๋ผ์ด์–ธํŠธ์™€ ๋™์‹œ์— ํ†ต์‹ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • pthread ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋”ฉ์„ ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
  • ๋ฎคํ…์Šค ์‚ฌ์šฉ
    • ์„œ๋ฒ„์—์„œ๋Š” ํด๋ผ์ด์–ธํŠธ์˜ ์—ฐ๊ฒฐ ๋ฐ ํ•ด์ œ์— ๋”ฐ๋ฅธ ๊ณต์œ  ์ž์› ์ ‘๊ทผ์„ ๋ณดํ˜ธํ•˜๊ธฐ ์œ„ํ•ด ๋ฎคํ…์Šค๋ฅผ ์‚ฌ์šฉ
    • pthread_mutex_lock ๋ฐ pthread_mutex_unlock ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒํ˜ธ๋ฐฐ์ œ๋ฅผ ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
  • ํด๋ผ์ด์–ธํŠธ ๊ด€๋ฆฌ
    • ์„œ๋ฒ„์—์„œ๋Š” ์ตœ๋Œ€ MAX_CLNT ๊ฐœ์˜ ํด๋ผ์ด์–ธํŠธ๋ฅผ ๊ด€๋ฆฌ
    • ํด๋ผ์ด์–ธํŠธ์˜ ์ƒํƒœ๋Š” CLIENT_INFO ๊ตฌ์กฐ์ฒด๋ฅผ ํ†ตํ•ด ๊ด€๋ฆฌ๋˜๋ฉฐ, ๊ฐ ํด๋ผ์ด์–ธํŠธ๋Š” ID, IP ์ฃผ์†Œ, ์†Œ์ผ“ ์‹๋ณ„์ž ๋“ฑ์„
      ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฉ”์‹œ์ง€ ์ „์†ก
    • ์„œ๋ฒ„์—์„œ๋Š” ํŠน์ • ์ˆ˜์‹ ์ž์—๊ฒŒ ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•˜๋Š” send_msg ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„
    • ์ˆ˜์‹ ์ž๊ฐ€ 'ALLMSG'์ธ ๊ฒฝ์šฐ์—๋Š” ๋ชจ๋“  ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ฉ”์‹œ์ง€๋ฅผ ์ „ํŒŒํ•˜๊ณ , 'IDLIST'์ธ ๊ฒฝ์šฐ์—๋Š”
      ํ˜„์žฌ ์ ‘์† ์ค‘์ธ ํด๋ผ์ด์–ธํŠธ์˜ ID ๋ชฉ๋ก์„ ์ „์†กํ•ฉ๋‹ˆ๋‹ค.

2. make ํŒŒ์ผ๋กœ ๋นŒ๋“œ

3. server, client ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰   

4. ๊ฒฐ๊ณผ ํ™•์ธ

3. ๐Ÿ“ฌ ์‹ค์Šต ๊ฒฐ๊ณผ

3.1. ์†Œ์ผ“ ํ†ต์‹ ์„ ์ด์šฉํ•œ ์ฑ„ํŒ… ํ”„๋กœ๊ทธ๋žจ ์ž‘์„ฑ

1. client.c

<cpp />
#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 <pthread.h> #include <signal.h> #define BUF_SIZE 100 #define NAME_SIZE 20 #define ARR_CNT 5 char name[NAME_SIZE] = "[Default]"; // ํด๋ผ์ด์–ธํŠธ์˜ ์ด๋ฆ„ char msg[BUF_SIZE]; // ๋ฉ”์‹œ์ง€๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฒ„ํผ void *send_msg(void *arg); void *recv_msg(void *arg); void error_handling(char *msg); int main(int argc, char *argv[]) { int sock; struct sockaddr_in serv_addr; pthread_t snd_thread, rcv_thread; void *thread_return; // ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ 4๊ฐœ๊ฐ€ ์•„๋‹ ์‹œ ์•ˆ๋‚ด ๋ฐ ์ข…๋ฃŒ(ํ”„๋กœ๊ทธ๋žจ, IP, ํฌํŠธ, ํด๋ผ์ด์–ธํŠธ ์ด๋ฆ„) if (argc != 4) { printf("Usage : %s <IP> <port> <name>\n", argv[0]); exit(1); } // ํด๋ผ์ด์–ธํŠธ ์ด๋ฆ„ ์„ค์ • sprintf(name, "%s", argv[3]); // ์†Œ์ผ“ ์ƒ์„ฑ sock = socket(PF_INET, SOCK_STREAM, 0); if (sock == -1) error_handling("socket() error"); // ์„œ๋ฒ„ ์ฃผ์†Œ ์„ค์ • memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr(argv[1]); serv_addr.sin_port = htons(atoi(argv[2])); // ์„œ๋ฒ„์— ์—ฐ๊ฒฐ if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1) error_handling("connect() error"); // ํด๋ผ์ด์–ธํŠธ์˜ ์ด๋ฆ„๊ณผ "PASSWD"๋ฅผ ์„œ๋ฒ„์— ์ „์†ก sprintf(msg, "[%s:PASSWD]", name); write(sock, msg, strlen(msg)); // ์“ฐ๋ ˆ๋“œ ์ƒ์„ฑ ๋ฐ ์กฐ์ธ pthread_create(&rcv_thread, NULL, recv_msg, (void *)&sock); pthread_create(&snd_thread, NULL, send_msg, (void *)&sock); pthread_join(snd_thread, &thread_return); // ์†Œ์ผ“ ๋‹ซ์€ ํ›„ ํ”„๋กœ๊ทธ๋žจ ์ข…๋ฃŒ close(sock); return 0; } // ๋ฉ”์‹œ์ง€๋ฅผ ์„œ๋ฒ„๋กœ ์ „์†กํ•˜๋Š” ํ•จ์ˆ˜ void *send_msg(void *arg) { int *sock = (int *)arg; int str_len; int ret; fd_set initset, newset; struct timeval tv; char name_msg[NAME_SIZE + BUF_SIZE + 2]; // ํŒŒ์ผ ์ดˆ๊ธฐํ™” FD_ZERO(&initset); FD_SET(STDIN_FILENO, &initset); // ๋ฉ”์‹œ์ง€ ์ž…๋ ฅ ๋Œ€๊ธฐ fputs("Input a message! [ID]msg (Default ID:ALLMSG)\n", stdout); while (1) { memset(msg, 0, sizeof(msg)); name_msg[0] = '\0'; tv.tv_sec = 1; tv.tv_usec = 0; newset = initset; ret = select(STDIN_FILENO + 1, &newset, NULL, NULL, &tv); if (FD_ISSET(STDIN_FILENO, &newset)) { // ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ๋ฉ”์‹œ์ง€ ์ž…๋ ฅ ๋ฐ›์Œ fgets(msg, BUF_SIZE, stdin); // "quit"์„ ์ž…๋ ฅํ•˜๋ฉด ํด๋ผ์ด์–ธํŠธ ์†Œ์ผ“์„ ์ข…๋ฃŒ if (!strncmp(msg, "quit\n", 5)) { *sock = -1; return NULL; } else if (msg[0] != '[') { // ๋ฉ”์‹œ์ง€์˜ ์ฒซ ๊ธ€์ž๊ฐ€ '['์ด ์•„๋‹ˆ๋ฉด "[ALLMSG]"๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ์ „์†ก strcat(name_msg, "[ALLMSG]"); strcat(name_msg, msg); } else strcpy(name_msg, msg); // ์„œ๋ฒ„๋กœ ๋ฉ”์‹œ์ง€ ์ „์†ก if (write(*sock, name_msg, strlen(name_msg)) <= 0) { *sock = -1; return NULL; }} if (ret == 0) { // ํƒ€์ž„์•„์›ƒ ๋ฐœ์ƒ ์‹œ if (*sock == -1) return NULL; }}} // ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜์‹ ํ•˜๋Š” ํ•จ์ˆ˜ void *recv_msg(void *arg) { int *sock = (int *)arg; int i; char *pToken; char *pArray[ARR_CNT] = {0}; char name_msg[NAME_SIZE + BUF_SIZE + 1]; int str_len; while (1) { memset(name_msg, 0x0, sizeof(name_msg)); str_len = read(*sock, name_msg, NAME_SIZE + BUF_SIZE); if (str_len <= 0) { // ์†Œ์ผ“์ด ๋‹ซํžŒ ๊ฒฝ์šฐ *sock = -1; return NULL; } name_msg[str_len] = 0; // ์ˆ˜์‹ ํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ํ‘œ์ค€ ์ถœ๋ ฅ์— ์ถœ๋ ฅ fputs(name_msg, stdout); // ๋ฉ”์‹œ์ง€ ํŒŒ์‹ฑ /* pToken = strtok(name_msg, "[:]"); i = 0; while (pToken != NULL) { pArray[i] = pToken; if (++i >= ARR_CNT) break; pToken = strtok(NULL, "[:]"); } printf("id:%s, msg:%s\n", pArray[0], pArray[1]); */ }} // ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ์ถœ๋ ฅ ํ›„ ํ”„๋กœ๊ทธ๋žจ์„ ์ข…๋ฃŒํ•˜๋Š” ํ•จ์ˆ˜ void error_handling(char *msg) { fputs(msg, stderr); fputc('\n', stderr); exit(1); }

 

2. server.c

<cpp />
#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> #include <sys/stat.h> #include <fcntl.h> #include <dirent.h> #include <sys/time.h> #include <time.h> #include <errno.h> #define BUF_SIZE 100 #define MAX_CLNT 32 #define ID_SIZE 10 #define ARR_CNT 5 #define DEBUG // ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ๋ฉ”์‹œ์ง€ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๋Š” ๊ตฌ์กฐ์ฒด typedef struct { char fd; char *from; char *to; char *msg; int len; } MSG_INFO; // ํด๋ผ์ด์–ธํŠธ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๋Š” ๊ตฌ์กฐ์ฒด typedef struct { int index; int fd; char ip[20]; char id[ID_SIZE]; char pw[ID_SIZE]; } CLIENT_INFO; void *clnt_connection(void *arg); void send_msg(MSG_INFO *msg_info, CLIENT_INFO *first_client_info); void error_handling(char *msg); void log_file(char *msgstr); int clnt_cnt = 0; 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; int sock_option = 1; pthread_t t_id[MAX_CLNT] = {0}; int str_len = 0; int i; char idpasswd[(ID_SIZE * 2) + 3]; char *pToken; char *pArray[ARR_CNT] = {0}; char msg[BUF_SIZE]; // ๋ฏธ๋ฆฌ ๋“ฑ๋ก๋œ ํด๋ผ์ด์–ธํŠธ ์ •๋ณด CLIENT_INFO client_info[MAX_CLNT] = {{0, -1, "", "KHJ_LIN", "PASSWD"}, \ {0,-1,"","KHJ_SQL","PASSWD"}, {0,-1,"","3","PASSWD"}, \ {0,-1,"","4","PASSWD"}, {0,-1,"","5","PASSWD"}, \ {0,-1,"","6","PASSWD"}, {0,-1,"","7","PASSWD"}, \ {0,-1,"","8","PASSWD"}, {0,-1,"","9","PASSWD"}, \ {0,-1,"","10","PASSWD"}, {0,-1,"","11","PASSWD"}, \ {0,-1,"","12","PASSWD"}, {0,-1,"","13","PASSWD"}, \ {0,-1,"","14","PASSWD"}, {0,-1,"","15","PASSWD"}, \ {0,-1,"","16","PASSWD"}, {0,-1,"","17","PASSWD"}, \ {0,-1,"","18","PASSWD"}, {0,-1,"","19","PASSWD"}, \ {0,-1,"","20","PASSWD"}, {0,-1,"","21","PASSWD"}, \ {0,-1,"","22","PASSWD"}, {0,-1,"","23","PASSWD"}, \ {0,-1,"","24","PASSWD"}, {0,-1,"","25","PASSWD"}, \ {0,-1,"","26","PASSWD"}, {0,-1,"","27","PASSWD"}, \ {0,-1,"","28","PASSWD"}, {0,-1,"","29","PASSWD"}, \ {0,-1,"","30","PASSWD"}, {0,-1,"","31","PASSWD"}, \ {0,-1,"","32","PASSWD"}}; // ์ปค๋งจ๋“œ ๋ผ์ธ์—์„œ ํฌํŠธ ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅ๋ฐ›์Œ if (argc != 2) { printf("Usage : %s <port>\n", argv[0]); exit(1); } fputs("IoT Server Start!!\n", stdout); // ๋ฎคํ…์Šค ์ดˆ๊ธฐํ™” if (pthread_mutex_init(&mutx, NULL)) error_handling("mutex init error"); // ์†Œ์ผ“ ์ƒ์„ฑ 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])); // ์†Œ์ผ“ ์˜ต์…˜ ์„ค์ • setsockopt(serv_sock, SOL_SOCKET, SO_REUSEADDR, (void *)&sock_option, sizeof(sock_option)); // ์†Œ์ผ“ ๋ฐ”์ธ๋”ฉ 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) { clnt_adr_sz = sizeof(clnt_adr); clnt_sock = accept(serv_sock, (struct sockaddr *)&clnt_adr, &clnt_adr_sz); if (clnt_cnt >= MAX_CLNT) { printf("socket full\n"); shutdown(clnt_sock, SHUT_WR); continue; } else if (clnt_sock < 0) { perror("accept()"); continue; } // ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ID์™€ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ฝ์Œ str_len = read(clnt_sock, idpasswd, sizeof(idpasswd)); idpasswd[str_len] = '\0'; if (str_len > 0) { i = 0; pToken = strtok(idpasswd, "[:]"); while (pToken != NULL) { pArray[i] = pToken; if (i++ >= ARR_CNT) break; pToken = strtok(NULL, "[:]"); } for (i = 0; i < MAX_CLNT; i++) { if (!strcmp(client_info[i].id, pArray[0])) { if (client_info[i].fd != -1) { // ์ด๋ฏธ ๋กœ๊ทธ์ธ๋œ ID์ธ ๊ฒฝ์šฐ sprintf(msg, "[%s] Already logged!\n", pArray[0]); write(clnt_sock, msg, strlen(msg)); log_file(msg); shutdown(clnt_sock, SHUT_WR); #if 1 // for MCU shutdown(client_info[i].fd, SHUT_WR); client_info[i].fd = -1; #endif break; } if (!strcmp(client_info[i].pw, pArray[1])) { // ID์™€ ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•˜๋Š” ๊ฒฝ์šฐ strcpy(client_info[i].ip, inet_ntoa(clnt_adr.sin_addr)); pthread_mutex_lock(&mutx); client_info[i].index = i; client_info[i].fd = clnt_sock; clnt_cnt++; pthread_mutex_unlock(&mutx); sprintf(msg, "[%s] New connected! (ip:%s,fd:%d,sockcnt:%d)\n", pArray[0], inet_ntoa(clnt_adr.sin_addr), clnt_sock, clnt_cnt); log_file(msg); write(clnt_sock, msg, strlen(msg)); pthread_create(t_id + i, NULL, clnt_connection, (void *)(client_info + i)); pthread_detach(t_id[i]); break; }}} if (i == MAX_CLNT) { // ์ธ์ฆ ์‹คํŒจํ•œ ๊ฒฝ์šฐ sprintf(msg, "[%s] Authentication Error!\n", pArray[0]); write(clnt_sock, msg, strlen(msg)); log_file(msg); shutdown(clnt_sock, SHUT_WR); } } else { // ์ฝ๊ธฐ ์‹คํŒจํ•œ ๊ฒฝ์šฐ shutdown(clnt_sock, SHUT_WR); }} return 0; } // ํด๋ผ์ด์–ธํŠธ ์“ฐ๋ ˆ๋“œ ํ•จ์ˆ˜ void *clnt_connection(void *arg) { CLIENT_INFO *client_info = (CLIENT_INFO *)arg; int str_len = 0; int index = client_info->index; char msg[BUF_SIZE]; char to_msg[MAX_CLNT * ID_SIZE + 1]; int i = 0; char *pToken; char *pArray[ARR_CNT] = {0}; char strBuff[130] = {0}; // ๋ฉ”์‹œ์ง€ ์ •๋ณด ๊ตฌ์กฐ์ฒด ๋ฐ ์ฒซ ๋ฒˆ์งธ ํด๋ผ์ด์–ธํŠธ ์ •๋ณด ์„ค์ • MSG_INFO msg_info; CLIENT_INFO *first_client_info; first_client_info = (CLIENT_INFO *)((void *)client_info - (void *)(sizeof(CLIENT_INFO) * index)); // ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ๋ฉ”์‹œ์ง€๋ฅผ ์ฝ์–ด์˜ด while (1) { memset(msg, 0x0, sizeof(msg)); str_len = read(client_info->fd, msg, sizeof(msg) - 1); if (str_len <= 0) break; msg[str_len] = '\0'; pToken = strtok(msg, "[:]"); i = 0; while (pToken != NULL) { pArray[i] = pToken; if (i++ >= ARR_CNT) break; pToken = strtok(NULL, "[:]"); } // ๋ฉ”์‹œ์ง€ ์ •๋ณด ์„ค์ • msg_info.fd = client_info->fd; msg_info.from = client_info->id; msg_info.to = pArray[0]; sprintf(to_msg, "[%s]%s", msg_info.from, pArray[1]); msg_info.msg = to_msg; msg_info.len = strlen(to_msg); sprintf(strBuff, "msg : [%s->%s] %s", msg_info.from, msg_info.to, pArray[1]); log_file(strBuff); // ๋ฉ”์‹œ์ง€ ์ „์†ก send_msg(&msg_info, first_client_info); } // ํด๋ผ์ด์–ธํŠธ ์†Œ์ผ“ ์ข…๋ฃŒ close(client_info->fd); sprintf(strBuff, "Disconnect ID:%s (ip:%s,fd:%d,sockcnt:%d)\n", client_info->id, client_info->ip, client_info->fd, clnt_cnt - 1); log_file(strBuff); // ๋ฎคํ…์Šค๋ฅผ ์ด์šฉํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ ์นด์šดํŠธ ๊ฐฑ์‹  pthread_mutex_lock(&mutx); clnt_cnt--; client_info->fd = -1; pthread_mutex_unlock(&mutx); return 0; } // ๋ฉ”์‹œ์ง€ ์ „์†ก ํ•จ์ˆ˜ void send_msg(MSG_INFO *msg_info, CLIENT_INFO *first_client_info) { int i = 0; if (!strcmp(msg_info->to, "ALLMSG")) { // ๋ชจ๋“  ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ฉ”์‹œ์ง€ ์ „์†ก for (i = 0; i < MAX_CLNT; i++) if ((first_client_info + i)->fd != -1) write((first_client_info + i)->fd, msg_info->msg, msg_info->len); } else if (!strcmp(msg_info->to, "IDLIST")) { // ๋ชจ๋“  ํด๋ผ์ด์–ธํŠธ์˜ ID ๋ชฉ๋ก์„ ์ „์†ก char *idlist = (char *)malloc(ID_SIZE * MAX_CLNT); msg_info->msg[strlen(msg_info->msg) - 1] = '\0'; strcpy(idlist, msg_info->msg); for (i = 0; i < MAX_CLNT; i++) { if ((first_client_info + i)->fd != -1) { strcat(idlist, (first_client_info + i)->id); strcat(idlist, " "); }} strcat(idlist, "\n"); write(msg_info->fd, idlist, strlen(idlist)); free(idlist); } else { // ํŠน์ • ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ฉ”์‹œ์ง€ ์ „์†ก for (i = 0; i < MAX_CLNT; i++) if ((first_client_info + i)->fd != -1) if (!strcmp(msg_info->to, (first_client_info + i)->id)) write((first_client_info + i)->fd, msg_info->msg, msg_info->len); }} // ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ์ถœ๋ ฅ ํ•จ์ˆ˜ void error_handling(char *msg) { fputs(msg, stderr); fputc('\n', stderr); exit(1); } // ๋กœ๊ทธ ํŒŒ์ผ์— ๋ฉ”์‹œ์ง€ ์ถœ๋ ฅ ํ•จ์ˆ˜ void log_file(char *msgstr) { fputs(msgstr, stdout); }

 

3.2. make ํŒŒ์ผ๋กœ ๋นŒ๋“œ

1. make ํŒŒ์ผ ์ž‘์„ฑ

<cpp />
# ์ปดํŒŒ์ผ๋Ÿฌ ์„ค์ • CC := gcc # ์‹คํ–‰ ํŒŒ์ผ ์ด๋ฆ„ TARGET_SRV := chat_server TARGET_CLN := chat_client # ๋งํฌ ๋ฐ ์Šค๋ ˆ๋”ฉ ํ”Œ๋ž˜๊ทธ LDFLAGS := -D_REENTRANT -pthread # ์†Œ์Šค ํŒŒ์ผ SRV_SOURCES := chat_server.c CLN_SOURCES := chat_client.c # ๋ชฉ์  ํŒŒ์ผ SRV_OBJECTS := $(SRV_SOURCES:.c=.o) CLN_OBJECTS := $(CLN_SOURCES:.c=.o) # ๋ชจ๋“  ๋ชฉํ‘œ ํŒŒ์ผ ๋นŒ๋“œ ๊ทœ์น™ all: $(TARGET_SRV) $(TARGET_CLN) # chat_server ์‹คํ–‰ ํŒŒ์ผ ๋นŒ๋“œ ๊ทœ์น™ $(TARGET_SRV): $(SRV_OBJECTS) $(CC) -o $@ $(SRV_OBJECTS) $(LDFLAGS) # chat_client ์‹คํ–‰ ํŒŒ์ผ ๋นŒ๋“œ ๊ทœ์น™ $(TARGET_CLN): $(CLN_OBJECTS) $(CC) -o $@ $(CLN_OBJECTS) $(LDFLAGS) # ๊ฐœ๋ณ„ ์†Œ์Šค ํŒŒ์ผ์„ ๋ชฉ์  ํŒŒ์ผ๋กœ ์ปดํŒŒ์ผ ๊ทœ์น™ %.o: %.c $(CC) -c -o $@ $< # ๋ชฉ์  ํŒŒ์ผ ๋ฐ ์‹คํ–‰ ํŒŒ์ผ ์ •๋ฆฌ ๊ทœ์น™ clean: rm -f *.o $(TARGET_SRV) $(TARGET_CLN) # ๋ชจ๋“  ํŒŒ์ผ, ์‹คํ–‰ ํŒŒ์ผ ํฌํ•จ ์ •๋ฆฌ ๊ทœ์น™ clean_all: rm -f *.o $(TARGET_SRV) $(TARGET_CLN)


2. ๋นŒ๋“œ ๊ฒฐ๊ณผ

server, client ๋ชจ๋‘ ์„ฑ๊ณต์ ์œผ๋กœ ๋นŒ๋“œ๋จ 

cleint, server ๋นŒ๋“œ ๊ฒฐ๊ณผ

3.3. server, client ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰   

1. server ์‹คํ–‰

ํ”„๋กœ๊ทธ๋žจ + ํฌํŠธ ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜์—ฌ ์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰

2. client ์‹คํ–‰

ํ”„๋กœ๊ทธ๋žจ + ์„œ๋ฒ„ ip + ํฌํŠธ ๋ฒˆํ˜ธ + ๋“ฑ๋ก๋œ ์•„์ด๋””๋ฅผ ์ž…๋ ฅํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰ 

3.4. ๊ฒฐ๊ณผ ํ™•์ธ 

  1. ๋“ฑ๋ก๋œ ID๋กœ ํด๋ผ์ด์–ธํŠธ ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•˜์—ฌ ์„ฑ๊ณต์ ์œผ๋กœ ์„œ๋ฒ„์™€ ์—ฐ๊ฒฐ๋˜๊ณ 
    ์„œ๋ฒ„์— ํ•ด๋‹น ๊ณ„์ • ์ ‘์†๋จ ๋ฉ”์‹œ์ง€๊ฐ€ ์ถœ๋ ฅ๋˜์—ˆ์Œ  
  2. ํด๋ผ์ด์–ธํŠธ์—์„œ ์ „์ฒด ์ฑ„ํŒ… ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ธ ๊ฒฐ๊ณผ ์„œ๋ฒ„ ๋ฐ ์ž์‹ ์˜ ํด๋ผ์ด์–ธํŠธ์— ํ•ด๋‹น ๋ฉ”์‹œ์ง€๊ฐ€ ์ถœ๋ ฅ๋˜์—ˆ์Œ
  3. ํด๋ผ์ด์–ธํŠธ์—์„œ ์—ฐ๊ฒฐ์„ ์ข…๋ฃŒ์‹œ ์„œ๋ฒ„์—์„œ Disconnect ID : KHJ_LIN + ip ์ฃผ์†Œ ์ถœ๋ ฅ๋จ

์„œ๋ฒ„์—์„œ ์ฑ„ํŒ… ๋ฐ›์€ ํ›„ ํ™”๋ฉด์— ์ถœ๋ ฅ ์ดํ›„ ๋‹ค์‹œ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ณด๋ƒ„
ํด๋ผ์ด์–ธํŠธ์—์„œ ์ฑ„ํŒ… ๋ณด๋ƒ„
์—ฐ๊ฒฐ ์ข…๋ฃŒ์‹œ ์„œ๋ฒ„ ๋ฉ”์‹œ์ง€

profile

Toby's Study Blog

@Toby12

ํฌ์ŠคํŒ…์ด ์ข‹์•˜๋‹ค๋ฉด "์ข‹์•„์š”โค๏ธ" ๋˜๋Š” "๊ตฌ๋…๐Ÿ‘๐Ÿป" ํ•ด์ฃผ์„ธ์š”!

๊ฒ€์ƒ‰ ํƒœ๊ทธ