질문&답변
클라우드/리눅스에 관한 질문과 답변을 주고 받는 곳입니다.
리눅스 분류

방갯수와 방인원을 무제한으로~!

작성자 정보

  • 강길상 작성
  • 작성일

컨텐츠 정보

본문

방갯수와 방인원을 무제한으로 소스좀 다시 코딩할려고 합니다

조언 부탁드립니다.

/*
정적인 유저 수와 방 개수의 한계를 가지는 채팅서버

  - 각 방이 가지는 유저에 대해서는 구조체로 관리
    동시처리에 대해서는 select이용
*/

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#include <unistd.h>
#include <stdio.h>

/*접속 포트 설정*/
#define SERVER_PORT 3000

/*
유저가 가질수 있는 데이터 : 소켓 기술자 / 대화명(귓속말등 기타 기능 추가시 서버에서 관리)
*/
struct user_node
{
 
 int user_sockfd;
};

/*
각 방의 인원은 5명이지만 Linked List로 유저에 대한 동적인 할당이 필요
*/
struct room_node
{
 char  room_name[10];
 struct user_node user_list[5];
 int user_count;
};

int  Socket(int family, int type, int protocol);
void Bind  (int sockfd, const struct sockaddr * socketaddr, socklen_t addrlen);
void Listen(int sockfd, int backlog);
int  Accept(int sockfd, struct sockaddr* cliaddr, socklen_t *addrlen);

int main(void)

 /*채팅에서의 방을 3개로 설정*/
 struct room_node roomlist[3];  
 
 int server_socket;
 int client_socket;
 
 struct sockaddr_in server_addr;
 struct sockaddr_in client_addr;
 int addrsize, msgsize;
 
 char BUFF[1024] = {0};
 fd_set readfd;
 int maxfd; 
 
 int room_index;
 int user_index;
 int tempsockfd;
 int temp_user_count;
 
 /*각 방에 대한  방이름 초기화*/
 strcpy(roomlist[0].room_name,"room1");
 strcpy(roomlist[1].room_name,"room2");
 strcpy(roomlist[2].room_name,"room3");
 
 /*각 방의 접속 사용사 수를 초기화*/
 roomlist[0].user_count = 0;
 roomlist[1].user_count = 0;
 roomlist[2].user_count = 0;

 /*1. 서버소켓생성*/
 server_socket = Socket(AF_INET, SOCK_STREAM, 0);
  
 /*서버 IP및 포트 설정*/
 server_addr.sin_family = AF_INET;
 server_addr.sin_port = htons(SERVER_PORT);
 server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
 memset(&(server_addr.sin_zero), 0, 8);
 
 Bind(server_socket, (struct sockaddr*)&server_addr, sizeof(struct sockaddr));
 
 Listen(server_socket, 0);
 
 FD_ZERO(&readfd);
 maxfd = server_socket;
  
 while(1)
 {
  /*서버에접속한 클라이언트 소켓 기술자[각 방의 유저구조체포함]를 fd_set에 설정*/
  FD_SET(server_socket, &readfd);
  
  for (room_index = 0; room_index < 3; room_index++)
  {
   for (user_index = 0; user_index < roomlist[room_index].user_count; user_index++)
   {
    tempsockfd = roomlist[room_index].user_list[user_index].user_sockfd;
    
    FD_SET(tempsockfd, &readfd);
   
    if (tempsockfd > maxfd)
     maxfd = tempsockfd;
   }
  } 
  maxfd = maxfd + 1;
  
  select(maxfd, &readfd, NULL, NULL,NULL);
  
  /*서버로의 접속이 있는 클라이언트에 대한 처리*/
  if (FD_ISSET(server_socket, &readfd))
  {
   addrsize = sizeof(struct sockaddr_in);
   client_socket = Accept(server_socket, (struct sockaddr*)&server_addr, &addrsize);
   

   msgsize = read(client_socket, BUFF, sizeof(BUFF));
   if (msgsize <=0)
   {
    printf("Enter user Error ");
    continue;
   }
   printf("Receive Message:%s ", BUFF);
  
    
   /*각 방이 5명으로 제한되어있으므로 해당 유저인원 체크*/ 
   if (BUFF[0] == '1')
   {
    printf("Login Room1 Count:%d ", roomlist[0].user_count);    
    
    if (roomlist[0].user_count == 5)
    {
     strcpy(BUFF, "User Count Overflow Error");
     write(client_socket, BUFF, strlen(BUFF));

     close(client_socket);          
     
     continue;
     /*인원초과*/
    }
    
    roomlist[0].user_list[roomlist[0].user_count].user_sockfd = client_socket;
    roomlist[0].user_count++;
    
    strcpy(BUFF, "ConnectOK");
    
    write(client_socket, BUFF, strlen(BUFF));
   }
   else if(BUFF[0] == '2')
   {    
    if (roomlist[1].user_count == 5)
    {
     strcpy(BUFF, "User Count OverFlow Error");
     write(client_socket, BUFF, strlen(BUFF));
     close(client_socket);
     continue;
     /*인원초과*/
    }
    
    roomlist[1].user_list[roomlist[1].user_count].user_sockfd = client_socket;
    roomlist[1].user_count++;

    strcpy(BUFF, "ConnectOK");
    write(client_socket, BUFF, strlen(BUFF));

   }
   else if(BUFF[0] == '3')
   {
    if (roomlist[2].user_count == 5)
    {
     strcpy(BUFF, "User Count OverFlow Error");
     write(client_socket, BUFF, strlen(BUFF));
     close(client_socket);
     
     continue;
     /*인원초과*/
    }
    
    roomlist[2].user_list[roomlist[2].user_count].user_sockfd = client_socket;
    roomlist[2].user_count++;
    strcpy(BUFF, "ConnectOK");
    write(client_socket, BUFF, strlen(BUFF));   
   }
   continue; 
  }

  /*
  각 방에 속한 모든 유저들의 소켓 기술자의 변화를 감지하여
  해당 수신 데이터에 대한 응답을 같은 방에 있는 유저에 한해서 송신
  */
  for (room_index = 0; room_index < 3; room_index++)
  {
   for (user_index = 0; user_index < roomlist[room_index].user_count; user_index++)
   {
    if (FD_ISSET(roomlist[room_index].user_list[user_index].user_sockfd, &readfd))
    {

     tempsockfd = roomlist[room_index].user_list[user_index].user_sockfd;

     msgsize = read(tempsockfd, BUFF,sizeof(BUFF));
     if (msgsize <= 0)
     {
      if (user_index == roomlist[room_index].user_count)
      {
       close(roomlist[room_index].user_list[user_index].user_sockfd);

       roomlist[room_index].user_count--;
      }
      else if (user_index < roomlist[room_index].user_count)
      {
       close(roomlist[room_index].user_list[user_index].user_sockfd);
       
       for (temp_user_count = user_index; temp_user_count < roomlist[room_index].user_count; temp_user_count++)
       {
        roomlist[room_index].user_list[temp_user_count] = roomlist[room_index].user_list[temp_user_count+1];
       }

       roomlist[room_index].user_count--;
      }
     }
     else
     {      
      printf("Receive Message=>%s ", BUFF, msgsize);

      for (temp_user_count = 0; temp_user_count < roomlist[room_index].user_count; temp_user_count++)
      {
       msgsize = strlen(BUFF);
       write(roomlist[room_index].user_list[temp_user_count].user_sockfd, BUFF,msgsize);      
      }
     }
    }
   }
  }   
  
 }
 return 0;

int Socket(int family, int type, int protocol)
{
 int result = 0;
 result = socket(family, type, protocol);
 if (result == -1)
 {
  printf("Socket Contructing Error ");
  exit(0);
 }
 return result;
}

void Bind(int sockfd, const struct sockaddr * socketaddr, socklen_t addrlen)
{
 int result = 0;
 result = bind(sockfd, socketaddr, addrlen);
 if (result == -1)
 {
  printf("Socket Binding Error ");
  exit(0);
 }
 else
 {
  printf("Success Binding ");
 }
 
}

void Listen(int sockfd, int backlog)
{
 int result = 0;
 result = listen(sockfd, backlog);
 if (result == -1)
 {
  printf("Listening Error ");
  exit(0);
 }
 else
 {
  printf("Success Listening ");
 }
}
 
int Accept(int sockfd, struct sockaddr* cliaddr, socklen_t *addrlen)
{
 int result = 0;
 result = accept(sockfd, cliaddr, addrlen);
 if (result == -1)
 {
  printf("Accept Error ");
  exit(0);
 }
 else
 {
  printf("Success Accept ");
 }
 return result;
}

관련자료

댓글 0
등록된 댓글이 없습니다.

공지사항


뉴스광장


  • 현재 회원수 :  60,138 명
  • 현재 강좌수 :  36,196 개
  • 현재 접속자 :  381 명