조경민 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);
}
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 |