#include <winsock2.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAXLINE 512
#define MAX_SOCK 64
char *escapechar = "exit";
int maxfdp1;
int num_chat = 0; // 채팅참가자수
int client_s[MAX_SOCK];
// 채팅탈퇴처리
void removeClient(int) // i번째참가자탈퇴
{
closesocket(client_s[i]); // 해당소켓닫기
if(i !=num_chat -1)
client_s[i] = client_s[num_chat -1];
num_chat --; // 채팅참가자수1명줄이기
printf("채팅참가자1명탈퇴. 현재참가자수= %d\n",num_chat);
}
// client_s[]내의최대소켓번호얻기(k는초기치)
int getmax(int k)
{
int max = k;
int r;
for(r = 0; r < num_chat ; r++) // 채팅참가자수만큼소켓배열탐색
if(client_s[r] > max)
max = client_s[r];
return max;
}
int main()
{
char rline[MAXLINE], my_msg[MAXLINE]; // buffer 생성
char *start = "Connetctd to chat_server\n"; // 최초연결시보내는메세지
int i,j,n;
SOCKET s, client_fd, clilen;
fd_set read_fds;
struct sockaddr_in client_addr, server_addr; // 소켓주소구조체선언
WSADATA wsa; // 윈소켓
// 윈속초기화
if(WSAStartup(MAKEWORD(2,2), &wsa) != 0)
exit(1);
// 초기소켓생성
if((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("Server: Can't open stream socket.");
exit(0);
}
// server_addr 구조체의내용세팅
ZeroMemory(&server_addr, sizeof(server_addr)); //초기화(0으로채운다)
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(9000);
// bind() if(bind(s,(struct sockaddr *)&server_addr,sizeof(server_addr)) < 0 ) {
printf("Server: Can't bind local address.\n");
exit(0);
}
//클라이언트로부터연결요청을기다림
listen(s,SOMAXCONN); // listen 접속대기(큐크기5)
maxfdp1 = s + 1; // 최대소켓번호+1
while(1)
{
FD_ZERO(&read_fds); // fd_set 초기화(0으로세팅)
FD_SET(s,&read_fds); // 소켓에해당하는file discripter를1로세팅
for(i=0; i<num_chat; i++) // ""
FD_SET(client_s[i], &read_fds);
maxfdp1 = getmax(s) +1; // maxfdp1 재계산
if(select(maxfdp1,&read_fds, (fd_set *)0, (fd_set *) 0, (struct timeval *) 0) < 0) // select setting
{
printf("select error =< 0 \n");
exit(0);
}
if(FD_ISSET(s, &read_fds)) // read_fds 중s에해당하는비트가세팅되있다면
{
int addrlen; // 의미없음ㅡㅡ.. 단순주소길이저장변수
addrlen = sizeof(client_addr);
// == 연결요청이있다면
clilen = sizeof(client_addr);
client_fd = accept(s, (struct sockaddr *)&client_addr, &addrlen); // accept()
if(client_fd == -1)
{
printf("accept error \n");
exit(0);
}
// 채팅클라이언트목록에추가
client_s[num_chat] = client_fd;
num_chat++; // 채팅참가자수1 증가
// "Connetctd to chat_server" 를접속한클라이언트에보냄 send(client_fd,start,strlen(start),0); printf("%d번째사용자추가,\n",num_chat);
}
//클라이언트가보낸메시지를모든클라이언트에게방송
for(i = 0; i<num_chat; i++) // 모든클라이언트검색
{
memset(rline,'\0',MAXLINE); // buffer 초기화
if(FD_ISSET(client_s[i],&read_fds)) // read 해당소켓에서read 할것이있는지확인
{
if((n = recv(client_s[i],rline,MAXLINE, 0 )) <= 0)
{
removeClient(i);
continue;
}
// 종료문자처리
if(strstr(rline,escapechar) != NULL) //"exit"가입력되면종료시키기
{
removeClient(i);
continue;
}
// 모든채팅참가자에게메시지방송
rline[n] = '\0';
for(j = 0; j < num_chat; j++)
send(client_s[j],rline,n,0);
printf("%s\n",rline);
}
}
}
closesocket(s); // closesocket()
WSACleanup(); // 윈속종료
return 0;
}
|