줏어온 윈도우즈용 소켓서버 소스

Posted by 빵빵빵
2009/06/12 11:37 전산(컴퓨터)/PC-Windows



정말 줏어온 서버소스-윈도우즈용
출처 : http://hengki.net/37

  1. ////////////////////////////////////////////////////////////////////////  
  2. //   
  3. // 비동기 소켓 서버  
  4. // 열혈강의 TCP/IP 21장의 예제를 클레스화  
  5. // 일단 에코 서버이며. 167 번째 줄에서 서버에서 해줄 코드를 입력하면 될듯..  
  6. //   
  7.   
  8. #define BUFSIZE 100  // 받아올 데이터 최대 크기  
  9. #define PORT 3000  // 포트번호 할당  
  10.   
  11. // 해더파일 선언  
  12. #include <winsock2.h>  
  13. #include <iostream>  
  14.   
  15. using namespace std;  
  16.   
  17. // ws2_32.lib 링크  
  18. #pragma comment(lib, "ws2_32.lib")  
  19.   
  20. class socketServer  
  21. {  
  22.  private:  
  23.   // 변수 선언   
  24.   WSADATA wsaData;  
  25.   SOCKET hServSock;  
  26.   SOCKADDR_IN servAddr;  
  27.   
  28.   SOCKET hSockArray[WSA_MAXIMUM_WAIT_EVENTS];   
  29.   //소켓 핸들배열  
  30.   //- 연결 요청이 들어올 때마다 생성되는 소켓의 핸들을 이 배열에 저장. (최대64)  
  31.   SOCKET hClntSock;  
  32.   SOCKADDR_IN clntAddr;  
  33.   
  34.   WSAEVENT hEventArray[WSA_MAXIMUM_WAIT_EVENTS];   
  35.   // 이벤트 배열   
  36.   WSAEVENT newEvent;  
  37.   WSANETWORKEVENTS netEvents;  
  38.   
  39.   int clntLen;  
  40.   int sockTotal;  
  41.   int index, i;    
  42.   char message[BUFSIZE];  
  43.   int strLen;  
  44.   
  45.   void CompressSockets(SOCKET* hSockArray, int omitIndex, int total);  
  46.   void CompressEvents(WSAEVENT* hEventArray, int omitIndex, int total);  
  47.   void ErrorHandling(char *message);  
  48.   
  49.  public:  
  50.   socketServer();  
  51.   int StartServer();  
  52. };  
  53.   
  54. socketServer::socketServer()  
  55. {  
  56.  sockTotal=0;  
  57. }  
  58.   
  59. int socketServer::StartServer()  
  60. {  
  61.  // 윈속 초기화 (성공시 0, 실패시 에러 코드리턴)  
  62.  if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){  
  63.   ErrorHandling("WSAStartup() error!");  
  64.  }  
  65.    
  66.  // 소켓 생성 (성공시 핸들을, 실패시 "INVALID_SOCKET" 반환)  
  67.  hServSock = socket(PF_INET, SOCK_STREAM, 0);  
  68.    
  69.  // 소켓 생성 실패 처리  
  70.  if(hServSock==INVALID_SOCKET){  
  71.   ErrorHandling("socket() error");  
  72.  }  
  73.   
  74.  // 소켓 통신을 위한 기본 정보   
  75.  servAddr.sin_family = AF_INET;  
  76.  servAddr.sin_addr.s_addr = htonl(INADDR_ANY);  
  77.  servAddr.sin_port = htons(PORT);  
  78.   
  79.  // 주소와 Port 할당 (바인드!!)  
  80.  if(bind(hServSock, (struct sockaddr *) &servAddr, sizeof(servAddr))==SOCKET_ERROR){  
  81.   ErrorHandling("bind() error");  
  82.  }  
  83.   
  84.  // 이벤트 발생을 확인 (성공시 0, 실패시 "SOCKET_ERROR" 반환)  
  85.  newEvent = WSACreateEvent();  
  86.  if(WSAEventSelect(hServSock, newEvent, FD_ACCEPT)==SOCKET_ERROR){  
  87.   ErrorHandling("WSAEventSelect() error");  
  88.  }  
  89.   
  90.  // 연결 대기 요청 상태로의 진입 (신호가 들어올때까지 대기)  
  91.  if(listen(hServSock, 5)==SOCKET_ERROR){  
  92.   ErrorHandling("listen() error");  
  93.  }  
  94.   
  95.  // 서버 소켓 핸들 정보  
  96.  hSockArray[sockTotal]=hServSock;  
  97.   
  98.  // 이벤트 오브젝트 핸들 정보  
  99.  hEventArray[sockTotal]=newEvent;  
  100.   
  101.  // 전체 소켓수  
  102.  sockTotal++;  
  103.   
  104.  // 루프  
  105.  while(1)  
  106.  {  
  107.   // 이벤트 종류 구분하기(WSAWaitForMultipleEvents)  
  108.   index = WSAWaitForMultipleEvents(sockTotal, hEventArray, FALSE, WSA_INFINITE, FALSE);  
  109.   index = index-WSA_WAIT_EVENT_0;  
  110.   
  111.   for(i=index; i<sockTotal; i++)  
  112.   {  
  113.    index = WSAWaitForMultipleEvents(1, &hEventArray[i], TRUE, 0, FALSE);     
  114.      
  115.    if((index==WSA_WAIT_FAILED || index==WSA_WAIT_TIMEOUT)) continue;  
  116.    else  
  117.    {  
  118.     index = i;  
  119.     WSAEnumNetworkEvents(hSockArray[index], hEventArray[index], &netEvents);  
  120.   
  121.     // 초기 연결 요청의 경우.  
  122.     if(netEvents.lNetworkEvents & FD_ACCEPT)   
  123.     {  
  124.      if(netEvents.iErrorCode[FD_ACCEPT_BIT] != 0)  
  125.      {  
  126.       puts("Accept Error");  
  127.       break;  
  128.      }  
  129.   
  130.      clntLen = sizeof(clntAddr);  
  131.        
  132.      // 연결을 수락 (accept | 성공시 소켓핸들 실패시 "INVALID_SOCKET" 반환)  
  133.      hClntSock = accept(hSockArray[index], (SOCKADDR*)&clntAddr, &clntLen);  
  134.   
  135.      // 이벤트 커널 오브젝트 생성(WSACreateEvent)  
  136.      newEvent=WSACreateEvent();  
  137.   
  138.      // 이벤트 발생 유무 확인(WSAEventSelect)  
  139.      WSAEventSelect(hClntSock, newEvent, FD_READ|FD_CLOSE);  
  140.   
  141.      hEventArray[sockTotal]=newEvent;  
  142.      hSockArray[sockTotal]=hClntSock;  
  143.      sockTotal++;  
  144.       
  145.      printf("새로 연결된 소켓의 핸들 %d \n", hClntSock);  
  146.     }  
  147.       
  148.     // 데이터 전송해올 경우.  
  149.     if(netEvents.lNetworkEvents & FD_READ)   
  150.     {  
  151.      if(netEvents.iErrorCode[FD_READ_BIT] != 0)  
  152.      {  
  153.       puts("Read Error");  
  154.       break;  
  155.      }  
  156.   
  157. ////////////////////////////////////////////////////////////////////////  
  158. ////////////////////////////////////////////////////////////////////////  
  159. ////////////////////////////////////////////////////////////////////////  
  160. //  
  161. //  서버 작업은 여기서 다하겠지..  
  162. //  
  163.   
  164.      // 데이터를 받음 (message에 받은 데이터를 담음)  
  165.      strLen=recv(hSockArray[index-WSA_WAIT_EVENT_0],message, sizeof(message), 0);       
  166.        
  167.      // 데이터 끝에 널값 입력  
  168.      message[strLen]=0;  
  169.        
  170.      // 에코(데이터를준 클라이언트에 다시 데이터쏘기)  
  171.      send(hSockArray[index-WSA_WAIT_EVENT_0], message, strLen,0);  
  172.        
  173.      // 예의상 화면에도 한번 보여줘야지  
  174.      cout<<message;  
  175.   
  176. ////////////////////////////////////////////////////////////////////////  
  177. ////////////////////////////////////////////////////////////////////////  
  178. ////////////////////////////////////////////////////////////////////////  
  179.     }  
  180.   
  181.     // 연결 종료 요청의 경우.  
  182.     if(netEvents.lNetworkEvents & FD_CLOSE)  
  183.     {  
  184.      if(netEvents.iErrorCode[FD_CLOSE_BIT] != 0)  
  185.      {  
  186.       puts("Close Error");  
  187.       break;  
  188.      }  
  189.       
  190.      WSACloseEvent(hEventArray[index]);  
  191.        
  192.      // 소켓 종류  
  193.      closesocket(hSockArray[index]);  
  194.      printf("종료 된 소켓의 핸들 %d \n", hSockArray[index]);  
  195.   
  196.      sockTotal--;  
  197.        
  198.      // 배열 정리.  
  199.      CompressSockets(hSockArray, index, sockTotal);  
  200.      CompressEvents(hEventArray, index, sockTotal);  
  201.     }  
  202.   
  203.    }//else  
  204.   }//for  
  205.  }//while  
  206.   
  207.     
  208.  // 할당 받은 리소스 반환.  
  209.  WSACleanup();  
  210.    
  211.  return 0;  
  212. }  
  213.   
  214. /************************************ 
  215. /*  
  216. /* CompressSockets 
  217. /* 
  218. */  
  219. void socketServer::CompressSockets(SOCKET* hSockArray, int omitIndex, int total)  
  220. {  
  221.  int i;  
  222.    
  223.  for(i=omitIndex; i<total; i++)  
  224.  {  
  225.   hSockArray[i]=hSockArray[i+1];  
  226.  }  
  227. }  
  228.   
  229. /************************************ 
  230. /*  
  231. /* CompressEvents 
  232. /* 
  233. */  
  234. void socketServer::CompressEvents(WSAEVENT* hEventArray, int omitIndex, int total)  
  235. {  
  236.  int i;  
  237.  for(i=omitIndex; i<total; i++)  
  238.  {  
  239.   hEventArray[i]=hEventArray[i+1];  
  240.  }  
  241. }  
  242.   
  243. /************************************ 
  244. /*  
  245. /* ErrorHandling 
  246. /* 
  247. */  
  248. void socketServer::ErrorHandling(char *message)  
  249. {   
  250.  fputs(message, stderr);  
  251.  fputc('\n', stderr);  
  252.  exit(1);  
  253. }  
  254.   
  255.   
  256. // 한번 실행해보는 메인함수!!  
  257. /************************************ 
  258. /*  
  259. /* main 
  260. /* 
  261. */  
  262. int main(){  
  263.   
  264.  // 서버 인스턴트  
  265.  socketServer server;  
  266.    
  267.  // 서버시작  
  268.  server.StartServer();  
  269. }  

2009/06/12 11:37 2009/06/12 11:37

이 글에는 트랙백을 보낼 수 없습니다