본문 바로가기

UNIX_LINUX_C_C++

select 함수를 이용한 채팅 서버

/*

select 함수를 이용한 채팅 서버

*/

#include "/home/jinyedge/lib/c/edge_lib.h"
#include "/home/jinyedge/lib/c/edge_linux.h"

/*-----------------------*/
#define BUF_LEN 2048
#define MAX_GUEST 20

typedef struct _Guest{
char name[20];
int sock;
} Guest;

typedef struct _Lobby{
Guest *guest[MAX_GUEST];
int n_guest;
int guest_cnt;
} Lobby;

/*-----------------------*/
fd_set read_fds;
Lobby lobby;

/*-----------------------*/
void lobby_exit(int conn);
void lobby_talk2all(char buf[], int guest_idx);
Guest * get_new_guest(int sock);

/*-----------------------*/
int main(void){
int sersock, clnsock;
int n_fds;
int i, k, r_code;
struct sockaddr_in client_addr;
size_t size;
char buf[BUF_LEN];

/*서버 소켓 생성*/
sersock = get_server_sock(8040);

/*접속대기*/
if(listen(sersock, 5) < 0){
perror ("listen");
exit(EXIT_FAILURE);
}
printf("wating...\n");

/*로비 구조체를 초기화한다.*/
for(i = 0; i < MAX_GUEST; i++){
lobby.guest[i] = NULL;
}
lobby.n_guest = 0;
lobby.guest_cnt = 0;

/*read_fds 를 초기화*/
FD_ZERO(&read_fds);

while(1){
/*소켓번호를 fs_set 구조체에 지정한다.*/
FD_SET(sersock, &read_fds);
for(i = 0; i < MAX_GUEST; i++){
if(lobby.guest[i] != NULL){FD_SET(lobby.guest[i]->sock, &read_fds);}
}

/*select() 호출*/
if((select(FD_SETSIZE, &read_fds, (fd_set *)0, (fd_set *)0
, (struct timeval *)0)) < 0 ){
perror("select");
exit(EXIT_FAILURE);
}

/*연결요청을 처리한다.*/
if(FD_ISSET(sersock, &read_fds)){
size = sizeof(client_addr);
clnsock = accept(sersock, (struct sockaddr *)&client_addr, &size);
if(clnsock > -1){
lobby.guest[clnsock] = get_new_guest(clnsock);
lobby.guest_cnt++;
printf("Server: connected from host %s, port %hd. \n"
, inet_ntoa(client_addr. sin_addr)
, ntohs(client_addr. sin_port));
}
}

/*메시지를 처리한다.*/
for(i = 0; i < MAX_GUEST; i++){
if(lobby.guest[i] == NULL){continue;}

if(FD_ISSET(lobby.guest[i]->sock, &read_fds)){
if(sock_recv(lobby.guest[i]->sock, buf, BUF_LEN) > 0){
printf("Received: %s: %s\n"
, lobby.guest[i]->name, buf);
lobby_talk2all(buf, i);
}
else{lobby_exit(i);}
}
}
}
close(sersock);
}

/*-----------------------*/
void lobby_exit(int n){
FD_CLR(lobby.guest[n]->sock, &read_fds);
close(lobby.guest[n]->sock);
free(lobby.guest[n]);
lobby.guest[n] = NULL;
lobby.n_guest--;
}

/*-----------------------*/
void lobby_talk2all(char buf[], int guest_idx){
int i;
char w_buf[2048];

sprintf(w_buf, "%s: %s", lobby.guest[guest_idx]->name, buf);

for(i = 0; i < MAX_GUEST; i++){
if(lobby.guest[i] != NULL){
if(sock_send(lobby.guest[i]->sock, w_buf) < 0){lobby_exit(i);}
}
}
}

/*-----------------------*/
Guest * get_new_guest(int sock){
Guest *temp;

temp = (Guest *)malloc(sizeof(Guest));
sprintf(temp->name, "guest%d", lobby.guest_cnt);
temp->sock = sock;

return temp;
}

#include "/home/jinyedge/lib/c/edge_lib.c"
#include "/home/jinyedge/lib/c/edge_linux.c"

'UNIX_LINUX_C_C++' 카테고리의 다른 글

[공유메모리] 데이터 넣는 방법  (0) 2011.10.16
dialogic programming example - async mode  (0) 2011.10.16
날짜,pthread,도메인  (0) 2011.10.16
[펌] C 에서의 문자열  (0) 2011.10.16
[펌] str error result  (0) 2011.10.16