조경민 bro(bro@shinbiro.com)
2002년 8월 7일 수요일, 오후 10:24:29
===========================================================

Winsock에서 비동기 소켓으로 하는 방법은 세가지가 있죠?
1. socketioctl ( FIONBIO) 로 비동기 전환  select 이용해서 이벤트 받죠?
2. WSAAyncSelect - 윈도우의 메시지를 이벤트로 받음
3. WSAEventSelect - 이것이 아마 님이 원하는 GUI안쓰고 Win32 이벤트 객체를 이용해 이벤트를 받는거죠.

딴건 똑같고요. 뒷부분이 오버랩이 아니면 말짱 황이죠..
SOCKET s = WSASocket(nAddressFormat, nSocketType, nProtocolType, NULL, 0, WSA_FLAG_OVERLAPPED);

담엔 Win32이벤트로 네트워크 이벤트를 받겠다고 해야겠죠.
WSAEVENT m_hWSAEvent = WSACreateEvent();
WSAEventSelect(m_hSocket, m_hWSAEvent, lEvent)

그리곤  bind 를 하시든지 connect를 하시든지.listen하시든지 하시고요.

이 소켓을 위한 담당 스레드를 생성하시고 아래처럼 하셔서 네트워크 이벤트를 감지해야 겠죠..

WSAEVENT EventToWaitFor[2];
    // 처리할 소켓 이벤트
    EventToWaitFor[0] =  m_hCloseEvent;                // 사용자에 의한 강제 소켓파기에 대한 이벤트핸들링용
    EventToWaitFor[0] =  m_hWSAEvent;                // 소켓 대기 이벤트

   while (TRUE)
    {
        // 세가지 이벤트에 대해서 하나라도 발생할때까지 TimeOut 대기를 한다.
  DWORD dwHandleSignaled =  
   WSAWaitForMultipleEvents(1, EventToWaitFor, FALSE, pSocket->m_dwStepTimeout, TRUE);//INFINITE);
        switch(dwHandleSignaled)
       {
         case WSA_WAIT_EVENT_0:     // CloseEvent가 발생하였다.
        {
            // Time to exit.
            return;
         }
        break;
        case WSA_WAIT_EVENT_0 + 1: // SocketEvent가 발생하였다.
         {
          WSANETWORKEVENTS NetEvents;
         // 어떤 SocketEvent가 발생하였는지 알아본다.
         int ce = ::WSAEnumNetworkEvents(pSocket->m_hSocket, pSocket->m_hWSAEvent, &NetEvents);
        if (NetEvents.lNetworkEvents & FD_READ) //notification of readiness for reading
       {
       pSocket->OnReceive(NetEvents.iErrorCode[FD_READ_BIT]);
        }
       if (NetEvents.lNetworkEvents & FD_WRITE) // notification of readiness for writing
        {
         pSocket->OnSend(NetEvents.iErrorCode[FD_WRITE_BIT]);
        }
            : 이런식으로 네트워크 이벤트를 하나씩 핸들링해 갑니다.


그리고 마지막으로 님이 원하신다던 오버랩드 완료 루틴을 작성하시면 되겠죠.

///////////////////////////////////////////////////////////////
// Overlapped I/O with Completion Rouetione
///////////////////////////////////////////////////////////////
// 만일 보낼때 WSABUF로 짤라 보내면 받을때는 받는 버퍼가 크더라도
// 짤라보낸 만큼씩만 받는다.
// 만일 받는 WSABUF가 받으려는 버퍼보다 작을땐 받을수있는 버퍼만큼 받고
// 다음번에 또 받게 된다.
void CALLBACK CompletionROUTINE( IN DWORD dwError, IN DWORD cbTransferred,
                                        IN LPWSAOVERLAPPED lpOverlapped,  IN DWORD dwFlags)
{
        static int tryed = 0;
        char sz[1000];
        wsprintf( sz, "CompletionROUTINE : %d Transfered", cbTransferred );
        wbuf.buf[ 20 ] = '\0';
        //MessageBox( NULL, wbuf.buf , sz, MB_OK);
        CClientSocket::ms_nRecved+=cbTransferred;
        TRACE("<%d> %d recved %s\r\n", tryed++, CClientSocket::ms_nRecved, sz );
        
}
  
// 받을것이 있넹 그럼 완료 루틴으로 해보잣
void CClientSocket::OnReceive(int nErrorCode)
{
        WSAOVERLAPPED ov = {0,};
        DWORD dwRecved = 0;
        DWORD dwFlag = 0;
        int nRet = 0;        
                
        nRet = WSARecv( m_hSocket, &wbuf, 1,  &dwRecved, &dwFlag , &ov, CompletionROUTINE );
        // NULL로 주면 완료루틴을 안탄다.
        //nRet = WSARecv( m_hSocket, &wbuf, 1,  &dwRecved, &dwFlag , NULL, CompletionROUTINE );
        
        // Alertable wait thread로 만들어야한다.
        SleepEx(INFINITE, TRUE);
}

'KB > MFC/Win32' 카테고리의 다른 글

메세지 크래커  (0) 2004.04.29
[DB] ODBC 데이타소스 생성하기 (DSN 생성)  (0) 2004.04.28
[MSDN] Ole Connection String  (0) 2004.04.28
OLE자동화_작업전환다시시도안나타나게  (0) 2004.04.28
네트워크 접속 방법  (0) 2004.04.28

+ Recent posts