'이벤트셀렉트'에 해당되는 글 3건

  1. 2010.02.05 EventSelect(클)
  2. 2010.02.05 EventSelect(서버)
  3. 2010.02.05 EventSelect란?

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

#define YOURIP "192.168.34.103"
#define YOURPORT 1100


struct App
{
 SOCKET sarr[WSA_MAXIMUM_WAIT_EVENTS];
 HANDLE hEarr[WSA_MAXIMUM_WAIT_EVENTS];
 HANDLE hFileArr[WSA_MAXIMUM_WAIT_EVENTS];
 int now;
};

void connectProc(int index);
void writeProc(int index);
void CloseProc(int index);
void DeleteSocket(int index);
void InitEvent(SOCKET sock);
void SendData(int index);


extern App app;




#include "event.h"

using namespace std;

App app; 

 

void main()
{
 WSADATA wsadata;
 WSAStartup(MAKEWORD(2,2),&wsadata);
 
 SOCKET sock;
 sock = socket(AF_INET, SOCK_STREAM, 0);

 SOCKADDR_IN client = {0,};

 client.sin_addr.s_addr = inet_addr(YOURIP);
 client.sin_family = AF_INET;
 client.sin_port = htons(YOURPORT);
 
 
 InitEvent(sock);
 
 WSAEventSelect(app.sarr[app.now],app.hEarr[app.now],FD_CONNECT);
 connect(sock,(SOCKADDR *)&client,sizeof(client));

 app.now++;

 WSANETWORKEVENTS ev;
 int index;
  
  

 while(1)
 {
  index = WSAWaitForMultipleEvents(app.now,app.hEarr,FALSE,WSA_INFINITE,FALSE);
  index -=  WSA_WAIT_EVENT_0;
  WSAEnumNetworkEvents(app.sarr[index],app.hEarr[index],&ev);

  switch(ev.lNetworkEvents)
  {
  case FD_CONNECT:
   connectProc(index);
   break;
  case FD_WRITE:
   writeProc(index);
   break;
  case FD_CLOSE:
   CloseProc(index);
   break;
  } 
 }
 

 WSACleanup();
}


void connectProc(int index)
{
 SOCKET sock = app.sarr[index];
 DeleteSocket(index);
 
 InitEvent(sock);
  
 WSAEventSelect(app.sarr[app.now], app.hEarr[app.now],FD_WRITE);
 app.now++;
}


void writeProc(int index)
{
 if(app.sarr[index])
 {
  while(1)
  {
   SendData(index);
  }
 }

}


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


 DeleteSocket(index);
}

void DeleteSocket(int index)
{
 app.now--;
 app.hEarr[index] = app.hEarr[app.now];
 app.sarr[index] = app.sarr[app.now];
}


void InitEvent(SOCKET sock)
{
 app.sarr[app.now] = sock;
 app.hEarr[app.now] = WSACreateEvent();
}


void SendData(int index)
{
 char str[100];
 printf("아무거나 입력해봐:\n");
 scanf("%s",str);

 SOCKET sock = app.sarr[index];
 send(sock,str,100,0);
}

'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 아몰라


#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 아몰라

1.Event Select모델 이란 ?

 

 : WSAEventSelect() 함수가 핵심적인 역할을 하는데 WSAAscyncSelect와 다르게 윈도우 메세지 형태  대신 이벤트 객체를 통해서 네트워크 이벤트를 감지 하고 이벤트 객체를 관찰함으로써 스레드를 사용하지 않고도 여러 개의 소켓을 처리 가능한 네트워크 모델.

 

 

2. 동작 원리

  : 소켓과 이벤트 객체를 연결 소켓 에 대한 이벤트를 처리하는데 ,연결 이유는 발생한 이벤트를 이벤트 객체를 통해서 감지하기 위함인데 네트워크 이벤트가 발생할 때마다 이벤트 객체의 신호 상태를 통해 네트워크 이벤트 발생을 감지할 수 있다.

 

 

 

 

 

3. 입출력 절차

 

 

  WSACreateEvent() 함수를 이용하여 이벤트 객체를 생성한           .

WSAEventSelect() 함수를 이용하여 소켓에 이벤트 객체 연결 처리할 네트워크 연결

WSAWaitForMultipleEvents() 이벤트객체가 이벤트 발생유무를 확인 하기 위한 함수(신호 감지)

WSAEnumNetworkEvents() 함수를 호출하여 발생한 네트워크 이벤트 및 오류 를알아낸다

 

 

4.관련 함수 및 예제

 

1.    WSAEventSelect() 함수

 

 #include <winsock2.h>

int WSAEventSelect(SOCKET S, WSAEVENT hEventObject, long lNetworkEvents);

성공시 0, 실패시 SOCKET_ERROR 반환

SOCKET S   :   관찰대상인 소켓의 핸들 전달.

WSAEVENT hEventObject  :  이벤트 발생유무의 확인을 위한 이벤트객체 핸들

long lNetworkEvents : 감시하고자하는 이벤트의 종류 등록

 








S
에 전달된 핸들의 소켓에서 lNetworkEvents 에 전달된 이벤트중 하나가 발생하면, hEventObject에 전달된 핸들의 커널 오브젝트를 signaled(신호) 상태로 바꾸는 함수이다.

.

이벤트는 WSAAsyncSelect 모델 하고 같다.

 

 

 

 

2.    이벤트 객체 생성과 제거: WSACreateEvent(),WSACloseEvent()

 

WSAEVENT   WSACreateEvent ( ) ;

                                   성공: 이벤트 객체 핸들 리턴

                               실패: WSA_INVALID_EVENT 리턴

BOOL  WSACloseEvent (WSAEVENT hEvent) ;

                                       성공: TRUE, 실패: FALSE

 

 

 






예제 코드

 

void Doit(intindex)

{

   SOCKADDR_IN clientaddr;

   intlen = sizeof(clientaddr);

   SOCKETsock = sarr[index];

   sarr[cnt] = accept(sock,(SOCKADDR*)&clientaddr,&len);

   hEarr[cnt] = WSACreateEvent(); //이벤트 객체 생성

   WSAEventSelect(sarr[cnt],hEarr[cnt],FD_READ|FD_CLOSE);//소켓 ,객체 연결

   cnt++;

}

 

 

 











3. 이벤트 객체의 신호 상태 감지하기 :
WSAWaitForMultipleEvents() 함수

 

DWORD WSAWaitForMultipleEvents (

   DWORD cEvents,

   const WSAEVENT* lphEvents,

   BOOL fWaitAll,

   DWORD dwTimeout,

   BOOL fAlertable

) ;

          

 

 

 





DWORD cEvents, :
이벤트 객체의 수 (하나의 소켓에 여러 개의이벤트 객체가능)

const WSAEVENT* lphEvents, : 이벤트 객체의 배열의 시작 주소(최대 64개가능)

BOOL fWaitAll,: 전체 신호 상태 / 단일 신호 상태에 따른 리턴시기를 구분

(TRUE 전달시 배열안의 이벤트 객체 가 전부 신호 상태이어야 리턴 가능)

(FALSE 전달시 배열안의 이벤트 객체가 하나라도 신호 상태이어도 리턴 가능)

DWORD dwTimeout,: 신호상태 감시할 시간 설정 (WSA_INFINITE : 무한대기)

BOOL fAlertable: 입출력 완료 시기

리턴 : 리턴값에서 WSA_WAIT_EVENT_0 인 상수를 빼면 이벤트 객체배열에서 이벤트가 발생한 이벤트핸들의 인덱스 값이 된다. 2개이상일경우 에는 인덱스가 작은 것부터 값을 얻는다.

 

 

 

 

 

4.구체적인 네트워크 이벤트 알아내기 :

int WSAEnumNetworkEvents (

   SOCKET s,

   WSAEVENT hEventObject,

   LPWSANETWORKEVENTS lpNetworkEvents

) ;                        성공: 0, 실패: SOCKET_ERROR

 

 







 

  

 SOCKET s, : 이벤트가 발생한 소켓의 핸들 전달
WSAEVENT hEventObject, :  소켓과 연결된, 신호상태인 이벤트 객체핸들  LPWSANETWORKEVENTS lpNetworkEvents : 발생한 이벤트의 유형정보와 오류정보로 채워질 WSANETWORKEVENTS 구조체 변수의 주소 값 전달

 

  

 

 

예제 코드 (WSAWaitForMultipleEvents 함수,WSAEnumNetworkEvents함수)

WSANETWORKEVENTSev;

intindex;

while(1){

   index = WSAWaitForMultipleEvents (cnt,hEarr,FALSE,WSA_INFINITE,FALSE);//이벤트유무확인

   index  = index – WSA_WAIT_EVENT_0;

   WSAEnumNetworkEvents(sarr[index],hEarr[index],&ev);//구체적인 이벤트 오류 알아내기

   switch(ev.lNetworkEvents){

   caseFD_ACCEPT:

       //do it..    break;

   caseFD_READ:

       //do it..    break;

   caseFD_CLOSE:

       //do it.     break;

 

 

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

EventSelect(클)  (0) 2010.02.05
EventSelect(서버)  (0) 2010.02.05
ASyncSelect 예제  (1) 2010.02.04
소켓통신의 라이브러리 사용 선택 시 고려사항  (0) 2010.02.02
소켓함수 예제(로그인서버)  (0) 2010.01.25
Posted by 아몰라
이전버튼 1 이전버튼