#include "smartsock.h" #include <unistd.h>
int main(void) { int iSock; //소켓 함수의 반환 값을 받는 변수 int icSock[MAX_USER]; //accept의 반환 값을 받는 변수 int iRtn; struct sockaddr_in stAddr; socklen_t uiSockLen=sizeof(struct sockaddr); char cBuf[BUF_SIZE]; const char * cP; fd_set fdRead; unsigned int uiUser; unsigned int uiCnt, uiCnt2; int iMSock; //store greatest number in file descriptors
iSock = socket(AF_INET, SOCK_STREAM, 0); //AF_INET = 2, if(0 > iSock) { perror("socket : "); return -1; } // stAddr구조체에 socket연결을 위한 필수 정보 입력 setting bzero(&stAddr, sizeof(stAddr)); //구조체 비우기(0으로 채우기) stAddr.sin_family = AF_INET; //#define AF_INET 2 /* IP protocol family. */ stAddr.sin_addr.s_addr = inet_addr(IP); //IP와 PORT값은 헤더파일에 정의되어 있다. stAddr.sin_port = htons((PORT));
iRtn = bind(iSock, (struct sockaddr *)&stAddr,sizeof(stAddr)); if(iRtn < 0) { perror("bind : "); close(iSock);
return -2; } iRtn = listen(iSock, 5); if(iRtn != 0) { perror("listen : "); close(iSock);
return -3; } uiUser = 0; while(1) { // setting fd_set FD_ZERO(&fdRead); //fdRead 변수 1024byte 전부 0으로 세팅 FD_SET(0, &fdRead); //키보드 입력 감시 FD_SET(iSock, &fdRead); //접속 소켓 감시 iMSock = iSock; //소켓의 최대값 저장 -> select함수 첫번째 인자는 감시하는 파일 값 + 1기 때문이 이에 대한 최대값 저장
for(uiCnt = 0; uiCnt < uiUser; ++uiCnt) //사용자가 접속하면 해당 Fd를 set해주고 가장 높은 fd값을 저장 { FD_SET(icSock[uiCnt], &fdRead); //접속한 사용자수만큼의 icSock배열에 소켓 값이 들어있음으로 이를 감시 if(iMSock < icSock[uiCnt]) { iMSock = icSock[uiCnt]; //iMSock에 소켓의 최대값 저장 } }
select((iMSock+1), &fdRead, 0, 0, 0);//select 함수를 사용하여 감시해준다.(입력이 있을때까지 무한대기)
if( 0 != FD_ISSET(iSock, &fdRead) ) //랑데뷰 소켓이 set(1)되어 있으면(사람이 접속하면) accept함수를 받아서 대화 소켓을 열어준다. { icSock[uiUser] = accept(iSock, (struct sockaddr *)&stAddr, &uiSockLen); //대화 소켓 값을 icSock배열에 저장해준다. if(icSock[uiUser] < 0) { perror("Accept : "); continue; } printf("Incoming Client \n"); printf("Client IP :%s\n", inet_ntoa(stAddr.sin_addr)); //사용자가 접속하면 IP를 출력시켜준다. write(icSock[uiUser], "Welcome :)", sizeof("Welcome :)")); //접속자에게 "Welcome" 메세지 전송 ++uiUser; //사용자 수 + } if(0 != FD_ISSET(0, &fdRead)) //서버에서 입력 값이 있을 경우에 { iRtn = read(0, cBuf, MSG_SIZE); //키보드 값을 읽어 cBuf에 저장 cBuf[iRtn - 1] = 0; //\n\r을 제거하기 위해 문자열 끝에 0을 강제 삽입 for(uiCnt = 0; uiCnt < uiUser; ++uiCnt) { write(icSock[uiCnt], cBuf, MSG_SIZE);//모든 사용자에게 보낸다. //접속한 클라이언트에게 메세지 전송 } } for(uiCnt = 0; uiCnt < uiUser; ++uiCnt) //접속 클라이언트 대화 소켓을 순회하면서 대화내용이 있는지 확인 { if( 0 != FD_ISSET(icSock[uiCnt], &fdRead)) { read(icSock[uiCnt], cBuf, MSG_SIZE); //대화가 있으면 읽어들임 for(uiCnt2 = 0; uiCnt2 < uiUser; ++uiCnt2) { if(uiCnt != uiUser) write(icSock[uiCnt2] ,cBuf, MSG_SIZE); //모든 클라이언트들에게 내용을 전송 } if( 0 == strncmp(cBuf,MSG_END, strlen(MSG_END)) ) //클라이언트가 종료 메세지를 입력할 경우 { close(icSock[uiCnt]); //해당 소켓을 닫고 --uiUser; //uiUser 수를 줄여주고 icSock[uiCnt] = icSock[uiUser]; //빠져나간 자리에 가장 마지막에 들어온 유저의 소켓 번호를 넣어준다 } } }
} for(uiCnt = 0; uiCnt < uiUser; ++uiCnt) //종료시 열린 소켓을 모두 닫아준다. { close(icSock[uiCnt]); } close(iSock); return 0; } |