리눅스 채팅 서버의 다음 소스에서 어떻게하면 방 갯수와 접속자를 무제한으로 바꿀 수 있는지 조언좀 해주십시오.

maysuki의 이미지

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

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

#include
#include
#include
#include
#include
#include

/*접속 포트 설정*/
#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\n");
continue;
}
printf("Receive Message:%s\n", BUFF);


/*각 방이 5명으로 제한되어있으므로 해당 유저인원 체크*/
if (BUFF[0] == '1')
{
printf("Login Room1 Count:%d\n", 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\n", 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\n");
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\n");
exit(0);
}
else
{
printf("Success Binding\n");
}

}

void Listen(int sockfd, int backlog)
{
int result = 0;
result = listen(sockfd, backlog);
if (result == -1)
{
printf("Listening Error\n");
exit(0);
}
else
{
printf("Success Listening\n");
}
}

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

JuEUS-U의 이미지

(아무래도 code태그를 사용하시는것이.. -ㅅ-)

그냥 단순하게 Linked List를 쓰면 됩니다...라고 할수 있겠죠....
c++이면 list 자료형을 쓰면 무진장 편한데...
c이기 때문에 아무래도 조금 고생하셔야겠습니다 ㅡㅡ;;

먼저 Linked List 자료형을 선언하시고,

struct list
{
 list *prev; // 단방향을 써도 무방하겠지만, 안전하게 양방향 해주는게 속편합니다..
 list *next;
 void *data; // 방/사용자 둘 다 list 구조형을 써야되기때문에... 이래야 함수 짜기도 편하고...
};

여러가지 함수 ( insert( target, location, data ) , remove( target, location ) )를 만드신 다음,
정상적으로 작동하는지 확인하시고,,

room_node에

list *user_head;

이런 선언을 추가해야겠고요,,,,

그리고 아래쪽에 사용자 추가하는 부분을 고치셔야 할겁니다.
간단하게 위에서 만든 insert함수를 써서 하시면 되겠네요.

또 전역으로

list *room_head;

선언한 후에 역시 방 추가/제거는 간단하게 샤샥....

( 아무래도 이 문제의 핵심은 linked list인듯 하군요;;; )

maysuki의 이미지

죄송하지만 좀더 구체적으로 알려주시면 안될까요?

seaofmagic의 이미지

어느 학교이신지 궁금하군요. 제가 바로 지난주에 시험본 내용인데.
질답게시판에서 이후 두번째로 올리신걸 보니 많이 급하시군요.

Quote:

Linked List로 유저에 대한 동적인 할당이 필요

친절하게도 예제소스에서 방법을 알려주고 있군요!

참고하세요.
http://gamedeveloper.co.kr/12
http://www.winapi.co.kr/clec/cpp2/19-2-1.htm

---
Make Better Life.


---
Make Better Life.

maysuki의 이미지

근데 기간이 얼마 남지 않아서 혼자 짜기에는 넉넉치 않아서 혹시라도 알고 계신다면 소스에 추가하는 방법좀 알려주세요.