본문 바로가기
임베디드/C언어 소켓 통신

구조체 사용

by sj0020 2020. 10. 8.

server

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/select.h>

#define BUF_SIZE   100
#define SERVER_IP   INADDR_ANY
#define SERVER_PORT   "7777"

//구조체
struct user
{      //  < 여기 적어주는 _STUDENT 는 코드상 큰 의미는 없다. 하지만 적어주는 이유는 구조체가 중복되어 코딩되는 것을 방지하기 위해 관례적으로 적어준다.
   char id[20];
   char sock_num;
};

struct user us[20];  


void error_handling(char *buf);

int main(/*int argc, char *argv[]*/)
{   
   int sock_check ;
   int serv_sock, clnt_sock;
   struct sockaddr_in serv_adr, clnt_adr;
   struct timeval timeout;
   fd_set reads, cpy_reads;

   socklen_t adr_sz;
   int fd_max, str_len, fd_num, i;
   char buf[BUF_SIZE];
   
   /*if(argc!=2) {
      printf("Usage : %s <port>\n", argv[0]);      
      exit(1);
   }
   printf("argc count: %d\n", argc);*/

   //1. server socket 생성
   serv_sock=socket(PF_INET, SOCK_STREAM, 0);

   //2. server socket 주소 정보 초기화
   memset(&serv_adr, 0, sizeof(serv_adr));
   serv_adr.sin_family=AF_INET;
   serv_adr.sin_addr.s_addr=htonl(SERVER_IP);
   serv_adr.sin_port=htons(atoi(SERVER_PORT));
   
   //3. server socket 주소 정보 binding
   if(bind(serv_sock, (struct sockaddr*) &serv_adr, sizeof(serv_adr))==-1)
      error_handling("bind() error");

   //4. client 접속 대기
   if(listen(serv_sock, 5)==-1)
      error_handling("listen() error");
   printf("읽고 있습니다.\n");

   FD_ZERO(&reads);
   FD_SET(serv_sock, &reads);
   fd_max=serv_sock;

   while(1)
   {
      cpy_reads=reads;
      timeout.tv_sec=5;
      timeout.tv_usec=5000; //위의 timeout.tv_sec 또는 timeout.tv_usec 하나만 써도 됨

      if((fd_num=select(fd_max+1, &cpy_reads, 0, 0, &timeout))==-1) //오류 발생시(-1일때)
         break;
      
      if(fd_num==0) // timeout  발생
         continue;

      for(i=0; i<fd_max+1; i++) // 폴링방식으로 계속 체크. fd_max'+1' 이유: fd_max가 서버라서 서버갯수
      {
         if(FD_ISSET(i, &cpy_reads))
         {
            if(i==serv_sock)     // connection request!
            {
               adr_sz=sizeof(clnt_adr);
               clnt_sock=
                  accept(serv_sock, (struct sockaddr*)&clnt_adr, &adr_sz);
               FD_SET(clnt_sock, &reads);
               
               if(fd_max<clnt_sock)
                  fd_max=clnt_sock;
               printf("정체를 밝혀라 : %d \n", clnt_sock);
               read(clnt_sock, buf, BUF_SIZE);
               
               sock_check = clnt_sock; // 어셉트 정보를 구조체에 저장

               us[sock_check].sock_num = clnt_sock; // 어셉트 정보를 구조체에 저장
               strcpy(us[sock_check].id, buf); // 어셉트 복사 저장

               

               us[sock_check].id[strlen(us[sock_check].id) - 1] = '\0';
               //buf[strlen(buf) - 1] = '\0';
               printf("------------------------------\n");
               printf("ID: %s 접속. \n", us[sock_check].id);
               printf("------------------------------\n");
               memset(buf, 0, BUF_SIZE);
            }
            else    // read message!
            {
               str_len=read(i, buf, BUF_SIZE);
               printf("str_len : %d\n", str_len);
               if(str_len==0)    // close request!
               {
                  FD_CLR(i, &reads);
                  close(i);
                  //us[i].id[strlen(us[i].id) - 1] = '\0'; 
                  printf("나가요. ~ : %d \n", i);
                  printf("ID: %s 퇴장. \n", us[i].id);
               }
               else
               {
                  //us[sock_check].id - 1 = '\0';
                  //us[i].id[strlen(us[i].id) - 1] = '\0'; 채팅 옆으로 나오게 하는게 하는거 혹시 한줄 밑으로 나오면 실행
                  printf("[%s]:", us[i].id);
                  printf("%s", buf);
                  write(i, buf, str_len);    // echo!
                  memset(buf, 0, BUF_SIZE);

               }
            }
         }
      }
   }
   close(serv_sock);
   return 0;
}

void error_handling(char *buf)
{
   fputs(buf, stderr);
   fputc('\n', stderr);
   exit(1);
}

 

'임베디드 > C언어 소켓 통신' 카테고리의 다른 글

TEST1008  (0) 2020.10.08
makefile  (0) 2020.10.08
enterID - 개행문자 없애기  (0) 2020.10.06
echo_client.c echo_selectserv.c  (0) 2020.09.29
echo_selectserv echo_client  (0) 2020.09.29