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:
댓글 달기