socket 배열
글쓴이: 익명 사용자 / 작성시간: 화, 2019/10/08 - 3:30오후
안녕하세요
클라이언트 관리 배열, epoll에서 클라이언트 관리 배열을 만들었는 데 여기서 어떻게 수정하면 될까요?
#include "libDefine.h"
void signalHandlerServer(int nSignal);
int setNonblockSocket(int nFileDescriptor);
int g_nServerSocket = -1; /* server socket file descriptor */
int g_nClientSocket = -1; /* client 관리 배열 */
int g_nClient[MAXCLIENT] = {0, };
int g_nClientCount = 0;
//int g_nClientSocket[MAXCLIENT] = {0, };
//int nClientCount = 0;
//int g_nClientSocket = -1; /* client socket file descriptor */
int main(int argc, char *argv[])
{
int nPort = -1;
char szMsg[SIZEBUFFER + 1] = {0,}; /* 수신용 버퍼 */
int nReadLength = 0; /* 받은 메시지 길이 저장 변수 */
struct sockaddr_in stClientAddr = {0,}; /* 클라이언트 주소 저장할 구조체 */
unsigned int uClientAddrSize = sizeof(stClientAddr); /* 클라이언트 주소 구조체의 크기 */
int nWriteLength = 0;
struct epoll_event stEvent = {0, };
struct epoll_event *pstEpollEvent[MAXCLIENT] = {0, };
//struct epoll_event stEpollEvent[MAXCLIENT] = {0, };
int nEpollFileDescriptor = -1;
int nEventCnt = 0;
int nIndex = 0;
/* signal 처리 */
signal(SIGINT, signalHandlerServer);
if (argc != 2)
{
printf("Usage : %s <port>\n", argv[0]);
exit(1);
}
/* port 예외 처리 port 범위 */
if(atoi(argv[1]) < 1024 || atoi(argv[1]) > 49151)
{
errHandle(errno, "port 사용하지 않는 포트입니다.\n");
exit(1);
}
else
{
nPort = atoi(argv[1]);
}
printf("서버 연결 중입니다.\n");
g_nServerSocket = serverSocket(nPort);
/* server socket 예외 처리 */
if(g_nServerSocket < 0)
{
errHandle(errno, "socket() error \n");
exit(1);
}
nEpollFileDescriptor = epoll_create(EPOLLSIZE);
if(nEpollFileDescriptor < 0)
{
errHandle(errno, "epoll file error \n");
close(g_nServerSocket);
g_nServerSocket = -1;
exit(1);
}
/* calloc() 메모리 할당 및 초기화 */
if((pstEpollEvent = calloc(EPOLLSIZE, sizeof(struct epoll_event))) == NULL)
{
errHandle(errno, "할당되지 않았습니다. \n");
close(g_nServerSocket);
g_nServerSocket = -1;
exit(1);
//close(nEpollFileDescriptor);
//nEpollFileDescriptor = -1;
}
setNonblockSocket(g_nServerSocket); /* server socket 에서 비동기 IO 설정 */
stEvent.events = EPOLLIN | EPOLLRDHUP | EPOLLET; /* event 발생 시 알림 */
stEvent.data.fd = g_nServerSocket; /* server socket 추가 */
/* server socket 상태 변화를 nEpollFileDescriptor 통해 알 수 있다. */
/* 예외 처리 추가 */
if(epoll_ctl(nEpollFileDescriptor, EPOLL_CTL_ADD, g_nServerSocket, &stEvent) < 0)
{
errHandle(errno, "server socket 상태 변화를 nEpollFileDescriptor 통해 관찰할 수 없습니다.");\
close(nEpollFileDescriptor);
nEpollFileDescriptor = -1;
close(g_nServerSocket);
g_nServerSocket = -1;
exit(1);
}
while(1)
{
/* nEpollFileDescriptor 의 사건 발생 시 pstEpollEvent 에 fd 채운다. */
nEventCnt = epoll_wait(nEpollFileDescriptor, pstEpollEvent, EPOLLSIZE, -1);
/* neventCnt 예외 처리 */
if(nEventCnt < 0)
{
errHandle(errno, "epoll wait error");
break;
}
else if(nEventCnt == 0)
{
break;
}
/* event 발생 횟수 출력 */
printf("return epoll 발생 \n");
for(nIndex = 0; nIndex < nEventCnt; nIndex++)
{
if(pstEpollEvent[nIndex].data.fd == g_nServerSocket)
{
g_nClientSocket = accept(g_nServerSocket, (struct sockaddr*) &stClientAddr, &uClientAddrSize);
for(g_nClientCount = 0; g_nClientCount < MAXCLIENT; g_nClientCount++)
{
g_nClient[g_nClientCount++] = g_nClientSocket;
}
//g_nClientSocket[nClientCount++] = g_nClientSocket[MAXCLIENT]; /* client socket 배열에 */
//g_nClientSocket[nClientCount++] = g_nClientSocket[MAXCLIENT];
/* client socket 예외 처리 client 배열 */
if(g_nClient[g_nClientCount] < 0)
{
errHandle(errno, "accept error");
continue;
}
else
{
printf("클라이언트 접속 IP : %s\n", inet_ntoa(stClientAddr.sin_addr));
printf("accept() client 접속 요청 수락");
}
setNonblockSocket(g_nClient[g_nClientCount]); /* client 소켓 넌블로킹으로 */
stEvent.events = EPOLLIN | EPOLLRDHUP | EPOLLET; /* event */
//stEvent.events = EPOLLIN | EPOLLET;
stEvent.data.fd = g_nClient[g_nClientCount]; /* client socket */
/* epoll_ctl() 로 pstEpollEvent 상태 변화를 nEpollFileDescriptor로 확인 */
if(epoll_ctl(nEpollFileDescriptor, EPOLL_CTL_ADD, g_nClient[g_nClientCount], &stEvent) < 0)
{
errHandle(errno, "client socket 상태 변화가 되지 않았습니다.");
close(g_nClientSocket[g_nClientCount]);
g_nClientSocket[g_nClientCount] = {0, };
continue;
}
printf("연결된 클라이언트 : %d\n", g_nClientSocket[g_nClientCount]);
}
else
{
//nReadLength = read(pstEpollEvent[nIndex].data.fd, szMsg, SIZEBUFFER);
nReadLength = read(pstEpollEvent[nIndex].data.fd, szMsg, SIZEBUFFER);
printf("받은 메시지 %s\n", szMsg);
if(nReadLength == 0)
{
//epoll_ctl(nEpollFileDescriptor, EPOLL_CTL_DEL, pstEpollEvent[nIndex].data.fd, &stEvent);
//close(nEpollFileDescriptor);
//nEpollFileDescriptor = -1;
epoll_ctl(nEpollFileDescriptor, EPOLL_CTL_DEL, pstEpollEvent[nIndex].data.fd, &stEvent);
close(pstEpollEvent[nIndex].data.fd);
printf("연결 종료된 클라이언트 %d\n", pstEpollEvent[nIndex].data.fd);
/*
epoll_ctl(nEpollFileDescriptor, EPOLL_CTL_DEL, pstEpollEvent[nIndex].data.fd, &stEvent);
close(pstEpollEvent[nIndex].data.fd);
printf("연결 종료된 클라이언트 %d\n", pstEpollEvent[nIndex].data.fd);
*/
continue;
//break;
}
else if(nReadLength < 0)
{
errHandle(errno, "read error \n");
if(errno != EAGAIN) /* EAGAIN 제외한 예외 처리 추가 */
{
errHandle(errno, "error \n");
epoll_ctl(nEpollFileDescriptor, EPOLL_CTL_DEL, pstEpollEvent[nIndex].data.fd, &stEvent);
close(pstEpollEvent[nIndex].data.fd);
continue;
}
else if(errno == EAGAIN) /* EAGAIN 예외 처리 */
{
errHandle(errno, "error \n");
epoll_ctl(nEpollFileDescriptor, EPOLL_CTL_DEL, pstEpollEvent[nIndex].data.fd, &stEvent);
close(pstEpollEvent[nIndex].data.fd);
continue;
}
/* 에러 예외 처리 추가 error */
/*
if(errno == EAGAIN || errno == EINVAL || errno == EBADF || errno == EEXIST || errno == ELOOP ||
errno == ENOENT || errno == ENOMEM || errno == ENOSPC || errno == EPERM) /* error 예외 처리 */
/*
{
errHandle(errno, "error \n");
epoll_ctl(nEpollFileDescriptor, EPOLL_CTL_DEL, pstEpollEvent[nIndex].data.fd, &stEvent);
//epoll_ctl(nEpollFileDescriptor, EPOLL_CTL_DEL, pstEpollEvent[nIndex].data.fd, &stEvent);
//close(nEpollFileDescriptor);
//nEpollFileDescriptor = -1;
close(pstEpollEvent[nIndex].data.fd);
break;
}
*/
}
else
{
for(nIndex=0; nIndex < g_nClientCount; nIndex++)//클라이언트 개수만큼
{
nWriteLength = write(pstEpollEvent[nIndex].data.fd, szMsg, nReadLength); //클라이언트들에게 메시지를 전달한다.
}
if(nWriteLength < 0)
{
errHandle(errno, "write error \n");
epoll_ctl(nEpollFileDescriptor, EPOLL_CTL_DEL, pstEpollEvent[nIndex].data.fd, &stEvent);
//close(nEpollFileDescriptor);
//nEpollFileDescriptor = -1;
close(pstEpollEvent[nIndex].data.fd);
continue;
}
memset(szMsg, 0, sizeof(szMsg));
}
}
for(nIndex = 0; nIndex < g_nClientCount; nIndex++) //배열의 갯수만큼
{
if(g_nClientSocket == g_nClient[nIndex]) //만약 현재 clientSock값이 배열의 값과 같다면
{
while(nIndex++ < g_nClientCount - 1) //클라이언트 개수 만큼
{
g_nClient[nIndex] = g_nClient[nIndex + 1]; //앞으로 땡긴다.
}
continue;
}
}
}
}
free(pstEpollEvent);
pstEpollEvent = NULL;
close(nEpollFileDescriptor);
nEpollFileDescriptor = -1;
nClientCount--; //클라이언트 개수 하나 감소
//close(g_nClientSocket);
//g_nClientSocket = -1;
close(g_nServerSocket);
g_nServerSocket = -1;
printf("연결이 끊어졌습니다. \n");
return 0;
}
void signalHandlerServer(int nSignal)
{
char szMessage[SIZEBUFFER] = {0,};
if (nSignal == SIGINT)
{
fputs("종료하시겠습니까?(y 입력) : ", stdout);
fgets(szMessage, SIZEBUFFER, stdin);
if(!strcasecmp(szMessage, "y\n"))
{
if(g_nClientSocket[nClientCount] >= 0)
{
close(g_nClient[nClientCount]);
//close(g_nClientSocket[MAXCLIENT]);
g_nClient[nClientCount] = {0, };
printf("client socket 종료되었습니다.\n");
}
if(g_nServerSocket >= 0)
{
close(g_nServerSocket);
g_nServerSocket = -1;
printf("server socket 종료되었습니다.\n");
}
exit(0);
}
}
}
int setNonblockSocket(int nFileDescriptor)
{
int nFlag = fcntl(nFileDescriptor, F_GETFL, 0);
/* nFlag 예외 처리 */
if(nFlag < 0)
{
errHandle(errno, "flag error");
exit(1);
}
fcntl(nFileDescriptor, F_SETFL, nFlag | O_NONBLOCK);
return 0;
}client
#include "libDefine.h"
void signalHandlerClient(int nSignal);
//int g_nClientSocket = -1;
int g_nClientSocket[MAXCLIENT] = {0, };
int g_nClientCount = 0;
//int g_nClientSocket[EPOLLSIZE] = {0, };
int main(int argc, char *argv[])
{
int nPort = -1;
char *pszAddr = NULL; /* ip 문자 입력받을 포인터 변수 */
char szMsg[SIZEBUFFER + 1] = {0,}; /* 서버에 보낼 메시지를 저장할 문자열 버퍼 */
int nReadLength = 0; /* 송수신 메시지의 문자열 길이 */
int nWriteLength = 0;
//int nEpollFileDescriptor = -1;
//struct epoll_event *pstEpollEvent = {0, };
//struct epoll_event stEpollEvent[EPOLLSIZE] = {0, };
//struct epoll_event stEvent = {0, };
//int nIndex = 0;
//int nReady = 0;
signal(SIGINT, signalHandlerClient);
/* port */
if (argc != 3)
{
printf("usage : %s <IP> <port> \n", argv[0]);
exit(1);
}
pszAddr = argv[1];
/* port 사용 범위 예외 처리 */
if(atoi(argv[2]) < 1024 || atoi(argv[2]) > 49151)
{
errHandle(errno, "port incorrect \n");
exit(1);
}
else
{
nPort = atoi(argv[2]);
}
g_nClientSocket = clientSocket(nPort, pszAddr);
if(g_nClientSocket < 0)
{
errHandle(errno, "socket() error \n");
exit(1);
}
while (1)
{
memset(szMsg, 0, sizeof(szMsg));
fputs("입력 메시지(Q는 종료, 버퍼(1024)까지 입력할 수 있습니다.) : ", stdout);
fgets(szMsg, sizeof(szMsg), stdin);
if(fgets(szMsg, sizeof(szMsg), stdin) == )
//szMsg[strlen(szMsg) - 1] = '\0';
/*
if(fgets(szMsg, sizeof(szMsg), stdin) == NULL)
{
fputs("입력 메시지 ", stdout);
fgets(szMsg, sizeof(szMsg), stdin);
fputs("입력 ", stdout);
}
*/
if(!strcasecmp(szMsg, "q\n"))
{
close(g_nClientSocket);
g_nClientSocket = -1;
break;
}
if((nWriteLength = write(g_nClientSocket, szMsg, strlen(szMsg))) < 0)
{
errHandle(errno, "write error \n");
close(g_nClientSocket);
g_nClientSocket = -1;
exit(1);
}
/*---Wait for data---*/
//nReady = epoll_wait(nEpollFileDescriptor, pstEpollEvent, EPOLLSIZE, 1000);
/*
for(nIndex = 0; nIndex < nReady; nIndex++)
{
if(pstEpollEvent[nIndex].events & EPOLLIN)
{
printf("data %d\n", pstEpollEvent[nIndex].data.fd);
memset(szMsg, 0, sizeof(szMsg));
read(g_nClientSocket, szMsg, sizeof(szMsg));
printf("Received %s\n", szMsg);
}
else if(pstEpollEvent[nIndex].events & EPOLLRDHUP)
{
printf("connect close %d\n", pstEpollEvent[nIndex].data.fd);
epoll_ctl(nEpollFileDescriptor, EPOLL_CTL_DEL, pstEpollEvent[nIndex].data.fd, NULL); // 종료된 클라이언트들의 소켓 디스크립터
close(pstEpollEvent[nIndex].data.fd);
printf("closed client: %d \n", pstEpollEvent[nIndex].data.fd);
}
}
*/
//num_ready = epoll_wait(epfd, events, MAX_EPOLL_EVENTS, 1000/*timeout*/);
memset(szMsg, 0, sizeof(szMsg));
if((nReadLength = read(g_nClientSocket, szMsg, nWriteLength)) < 0)
{
errHandle(errno, "read error \n");
close(g_nClientSocket);
g_nClientSocket = -1;
exit(1);
}
szMsg[nReadLength] = 0;
printf("서버로 받은 메시지 : %s\n", szMsg);
}
return 0;
}
void signalHandlerClient(int nSignal)
{
char szMessage[SIZEBUFFER] = {0,};
if (nSignal == SIGINT)
{
fputs("종료하시겠습니까?(y 입력) : ", stdout);
fgets(szMessage, SIZEBUFFER, stdin);
if(!strcasecmp(szMessage, "y\n"))
{
if(g_nClientSocket >= 0)
{
close(g_nClientSocket);
g_nClientSocket = -1;
printf("연결 종료되었습니다.\n");
}
exit(0);
}
}
}Forums:

댓글 달기