본문 바로가기

DEVELOPMENT/C/C++

[C/C++] 비동기식 에코 서버

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <winsock2.h>
  4.  
  5. #define BUF_SIZE 100
  6. #define PORT 3000
  7.  
  8. #pragma comment(lib, "ws2_32.lib")
  9.  
  10. void CompressSockets(SOCKET hSockArray[]int idx, int total);
  11. void CompressEvents(WSAEVENT hEventArr[]int idx, int total);
  12. void ErrorHandling(char* message);
  13.  
  14. int main(int argc, char *argv[])
  15. {
  16.     WSADATA wsaData;
  17.     SOCKET hServSock, hClntSock;
  18.     SOCKADDR_IN servAdr, clntAdr;
  19.  
  20.     SOCKET hSockArr[WSA_MAXIMUM_WAIT_EVENTS];
  21.     WSAEVENT hEventArr[WSA_MAXIMUM_WAIT_EVENTS];
  22.     WSAEVENT newEvent;
  23.     WSANETWORKEVENTS netEvents;
  24.  
  25.     int numOfClntSock = 0;
  26.     int strLen, i;
  27.     int posInfo, startIdx;
  28.     int clntAdrLen;
  29.     char msg[BUF_SIZE];
  30.     /*
  31.    
  32.     if (argc != 2)
  33.     {
  34.         printf("Usage : %s <PORT>\n", argv[0]);
  35.         exit(1);
  36.     }
  37.     */
  38.     if (WSAStartup(MAKEWORD(22), &wsaData) != 0)
  39.         ErrorHandling("WSAStartup() error");
  40.  
  41.     hServSock = socket(PF_INET, SOCK_STREAM, 0);
  42.  
  43.     memset(&servAdr, 0sizeof(servAdr));
  44.     servAdr.sin_family = AF_INET;
  45.     servAdr.sin_addr.s_addr = htonl(INADDR_ANY);
  46.     servAdr.sin_port = htons(PORT);
  47.  
  48.     if (bind(hServSock, (SOCKADDR*)&servAdr, sizeof(servAdr)) == SOCKET_ERROR)
  49.         ErrorHandling("bind() error");
  50.  
  51.     if (listen(hServSock, 5) == SOCKET_ERROR)
  52.         ErrorHandling("listen() error");
  53.  
  54.     newEvent = WSACreateEvent();
  55.     if (WSAEventSelect(hServSock, newEvent, FD_ACCEPT) == SOCKET_ERROR)
  56.         ErrorHandling("WSAEventSelect() error");
  57.  
  58.     hSockArr[numOfClntSock] = hServSock;
  59.     hEventArr[numOfClntSock] = newEvent;
  60.     numOfClntSock++;
  61.     while (1)
  62.     {
  63.         posInfo = WSAWaitForMultipleEvents(numOfClntSock, hEventArr, true, WSA_INFINITE, false);
  64.         startIdx = posInfo - WSA_WAIT_EVENT_0;
  65.         for (i = startIdx; i < numOfClntSock; i++)
  66.         {
  67.  
  68.             int sigEventIdx =
  69.                 WSAWaitForMultipleEvents(1, &hEventArr[i]true0false);
  70.             if ((sigEventIdx = WSA_WAIT_FAILED || sigEventIdx == WSA_WAIT_TIMEOUT))
  71.             {
  72.                 continue;
  73.             }
  74.             else
  75.             {
  76.                 sigEventIdx = i;
  77.                 WSAEnumNetworkEvents(hSockArr[sigEventIdx], hEventArr[sigEventIdx], &netEvents);
  78.                 if (netEvents.lNetworkEvents & FD_ACCEPT_BIT) // 연결 요청시
  79.                 {
  80.                     puts("Acept Error");
  81.                     break;
  82.                 }
  83.  
  84.                 clntAdrLen = sizeof(clntAdr);
  85.                 hClntSock = accept(hSockArr[sigEventIdx](SOCKADDR*)&clntAdr, &clntAdrLen);
  86.                 newEvent = WSACreateEvent();
  87.                 WSAEventSelect(hClntSock, newEvent, FD_READ | FD_CLOSE);
  88.  
  89.                 hEventArr[numOfClntSock] = newEvent;
  90.                 hSockArr[numOfClntSock] = hClntSock;
  91.                 numOfClntSock++;
  92.                 puts("connected new client...");
  93.             }
  94.  
  95.             if (netEvents.lNetworkEvents & FD_READ) // 데이터 수신 시
  96.             {
  97.                 if (netEvents.iErrorCode[FD_READ_BIT] != 0)
  98.                 {
  99.                     puts("Read error");
  100.                     break;
  101.                 }//if문 끝
  102.                 strLen = recv(hSockArr[sigEventIdx], msg, sizeof(msg)0);
  103.                 send(hSockArr[sigEventIdx], msg, strLen, 0);
  104.             }//if문 끝
  105.  
  106.             if (netEvents.lNetworkEvents & FD_CLOSE) // 종료 요청 시
  107.             {
  108.                 if (netEvents.iErrorCode[FD_CLOSE_BIT] != 0)
  109.                 {
  110.                     puts("Close error");
  111.                     break;
  112.                 }// if문 끝
  113.                 WSACloseEvent(hEventArr[sigEventIdx]);
  114.                 closesocket(hSockArr[sigEventIdx]);
  115.  
  116.                 numOfClntSock--;
  117.                 CompressSockets(hSockArr, sigEventIdx, numOfClntSock);
  118.                 CompressEvents(hEventArr, sigEventIdx, numOfClntSock);
  119.             }//if문 끝
  120.         }
  121.     }
  122.     WSACleanup();
  123.     return 0;
  124. }// end of main function
  125.  
  126. void CompressSockets(SOCKET hEventArr[]int idx, int total)
  127. {
  128.     int i;
  129.     for (i = idx; i<total; i++)
  130.     {
  131.         hEventArr[i] = hEventArr[i + 1];
  132.     }
  133. }
  134.  
  135. void CompressEvents(WSAEVENT hEventArr[]int idx, int total)
  136. {
  137.     int i;
  138.     for (i = idx; i<total; i++)
  139.     {
  140.         hEventArr[i] = hEventArr[i + 1];
  141.  
  142.     }
  143. }
  144.  
  145. void ErrorHandling(char *msg)
  146. {
  147.     fputs(msg, stderr);
  148.     fputc('\n', stderr);
  149.     exit(1);
  150. }