#pragma comment(lib,"ws2_32")
#include <winsock2.h>
#include <iostream>

using namespace std;

struct App
{
 SOCKET sarr[WSA_MAXIMUM_WAIT_EVENTS];  //WSA_MAXIMUM_WAIT_EVENTS 는 64로 정의되어있다.
 HANDLE hEarr[WSA_MAXIMUM_WAIT_EVENTS];   //64는 한 소켓이 소유할 수 있는 이벤트 객체 핸들의 최대갯수
 HANDLE hFileArr[WSA_MAXIMUM_WAIT_EVENTS];
 int now; //신호상태인 이벤트객체의 갯수
};

App app;

void AcceptProc(int index);
void ReadProc(int index);
void CloseProc(int index);

void main()
{
 WSADATA wsadata;
 WSAStartup(MAKEWORD(2,2),&wsadata);

 SOCKET sock;
 sock = socket(AF_INET,SOCK_STREAM,0);

 SOCKADDR_IN servaddr={0,};

 servaddr.sin_family = AF_INET;
 servaddr.sin_addr.s_addr = inet_addr("192.168.34.103");
 servaddr.sin_port = htons(1100);

 int re = bind(sock,(SOCKADDR *)&servaddr,sizeof(servaddr));
 re = listen(sock,5);
 app.sarr[app.now]=sock; //셋팅된 sock을 app.sarr[app.now]에 넣어준다.
 
 
 app.hEarr[app.now] = WSACreateEvent();  //이벤트객체를 생성
 WSAEventSelect(app.sarr[app.now],app.hEarr[app.now],FD_ACCEPT); 
 //app.sarr[app.now] 에서 FD_ACCEPT가 발생하면 app.hEarr[app.now]를 신호상태로 바꿔준다.

 app.now++; //생성됐으니 카운트 증가

 WSANETWORKEVENTS ev; //이벤트의 유형정보와 오류정보로 채워질 WSANETWORKEVENTS 구조체 변수


 int index;
 while(1)
 {
  index = WSAWaitForMultipleEvents(app.now,app.hEarr,FALSE,WSA_INFINITE,FALSE);
  index -= WSA_WAIT_EVENT_0;

//FALSE 이면 이벤트 객체중에서 하나라도 신호상태이면 index를 반환해준다.
//TRUE 이면 전부 신호상태이어야 반환된다.
//2개 이상 신호상태일시 인덱스 번호가 낮은 것이 반환된다.


  WSAEnumNetworkEvents(app.sarr[index],app.hEarr[index],&ev);
//이벤트가 발생한 소켓과 신호상태인 이벤트객체핸들에서 발생한이벤트의 유형정보와 오류정보가 WSANETWORKEVENTS 구조체의 주소값으로 전달된다.

  switch(ev.lNetworkEvents)
  {
  case FD_ACCEPT:
   AcceptProc(index);
   break;
  case FD_READ:
   ReadProc(index);
   break;
  case FD_CLOSE:
   CloseProc(index);
   break;
  }  
 }
 WSACleanup();
}

void AcceptProc(int index)
{
 SOCKADDR_IN clientaddr;
 int len = sizeof(clientaddr);
 SOCKET sock = app.sarr[index];
 app.sarr[app.now] = accept(sock,(SOCKADDR *)&clientaddr,&len);
 app.hEarr[app.now] = WSACreateEvent();
 WSAEventSelect(app.sarr[app.now],app.hEarr[app.now],FD_READ|FD_CLOSE);
 app.now++;
}

void ReadProc(int index)
{
 char buf[100];
 SOCKET sock = app.sarr[index];
 if(recv(sock,buf,100,0)<=0) //접속이 종료되었거나 에러가 나면 리턴
 {
  return;  
 }
 printf("%s\n", buf);
}

void CloseProc(int index)
{
 WSACloseEvent(app.hEarr[index]);
 closesocket(app.sarr[index]);

 app.now--;
 app.hEarr[index] = app.hEarr[app.now];
 app.sarr[index] = app.sarr[app.now];
}

'API & MFC > 네트워크프로그래밍' 카테고리의 다른 글

우아한 종료  (0) 2010.02.09
EventSelect(클)  (0) 2010.02.05
EventSelect란?  (0) 2010.02.05
ASyncSelect 예제  (1) 2010.02.04
소켓통신의 라이브러리 사용 선택 시 고려사항  (0) 2010.02.02
Posted by 아몰라