About WSAEventSelect Model Problem.
- From: "madmanahong" <madmanahong@xxxxxxx>
- Date: 30 May 2006 04:14:04 -0700
Greeting,
I Write a HTTP client by WSAEventSelect Model, I want to get file
data form HTTP server. I cut a file to piece and download every piece
from server. I send HTTP request, and wait for server back me file
data. when first piece, code worked well, and I receive
a 256K( every piece was 256K ) datas, but I want to get the next piece,
code was block
on WaitForSingleObject..
when I need to call WSAResetEvent to reset WSAEVENT.
The code like this and not long( about 150 lines ), thank you to
help me find what's
wrong.
struct SThread
{
HANDLE hHandle;
SOCKET hSocket;
WSAEVENT wEvent;
CHttpDown* pHost;
CPiece* pPiece; // the file piece
};
namespace{
UINT __stdcall HttpExecute( LPVOID pParam )
{
////////////////////////////////////////////////////////////////////////
// build the socket & connect the Http server
////////////////////////////////////////////////////////////////////////
SThread& sThread = *( SThread* )pParam;
sThread.hSocket = ::socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if ( sThread.hSocket == INVALID_SOCKET )
{
return -1;
}
sThread.wEvent = ::WSACreateEvent( );
if ( sThread.wEvent == WSA_INVALID_EVENT )
{
return -1;
}
////////////////////////////////////////////////////////////////////////
// select interested event type
////////////////////////////////////////////////////////////////////////
::WSAEventSelect( sThread.hSocket, sThread.wEvent, FD_CONNECT |
FD_READ | FD_WRITE | FD_CLOSE );
//////////////////
SOCKADDR_IN sockAddr;
memset( &sockAddr, 0, sizeof( sockAddr ) );
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons( sThread.pHost->GetPort( ) );
sockAddr.sin_addr.s_addr = inet_addr( sThread.pHost->GetHost( ) );
if ( sockAddr.sin_addr.s_addr == INADDR_NONE )
{
LPHOSTENT lphost;
lphost = gethostbyname( sThread.pHost->GetHost( ) );
if ( lphost )
{
sockAddr.sin_addr.s_addr = ( (LPIN_ADDR)lphost->h_addr )->s_addr;
}
else
{
WSASetLastError( WSAEINVAL );
return -1;
}
}
/////////////////////////////////////////////////////////////////////
// bContinue means all is over?
BOOL bContinue = FALSE;
do{
BOOL bComplete = FALSE; // is a piece complete ?
BOOL bFirstPacket = TRUE; // is first packet ? first have HTTP header
::connect( sThread.hSocket, ( sockaddr* )&sockAddr, sizeof( sockAddr )
);
////////////////////////////////////////////////////////////////////////
// DEAD LOOP for get net notify
for ( ;; )
{
////////////////////////////////////////////////////////////////////////
// BLOCK THIS!!!!!!!!!!!!!!!!!!!!
// WHEN second arrive here.
////////////////////////////////////////////////////////////////////////
DWORD dwRet = ::WaitForSingleObject( sThread.wEvent, WSA_INFINITE );
if ( dwRet == WSA_WAIT_EVENT_0 )
{
WSANETWORKEVENTS wNetEvent;
::WSAEnumNetworkEvents( sThread.hSocket, sThread.wEvent, &wNetEvent
);
if ( wNetEvent.lNetworkEvents & FD_CONNECT )
{
if ( wNetEvent.iErrorCode[ FD_CONNECT_BIT ] )
{
APPTRACE( "FD_CONNECT_ERROR -- %d\n", wNetEvent.iErrorCode[
FD_CONNECT_BIT ] );
break;
}
// get piece length
and fill the HTTP header
CString strRange;
strRange.Format( "Range: bytes=%d-%d",
( DWORD )sThread.pPiece->GetPieceStart( ),
( DWORD )sThread.pPiece->GetPieceStart( ) +
sThread.pPiece->GetPieceSize( ) - 1 );
APPTRACE( "%s\n", strRange );
strRange += "\r\n";
CString strTemp = sThread.pHost->GetReqHeader( );
strTemp += strRange;
strTemp += "\r\n";
::send( sThread.hSocket, strTemp.GetBuffer( 0 ), strTemp.GetLength(
), 0 );
bFirstPacket = TRUE;
}
else if ( wNetEvent.lNetworkEvents & FD_READ )
{
if ( wNetEvent.iErrorCode[ FD_READ_BIT ] )
{
APPTRACE( "FD_READ_ERROR -- %d\n", wNetEvent.iErrorCode[
FD_READ_BIT ] );
break;
}
BYTE byBuffer[ 2048 ];
BYTE* pTemp = byBuffer;
INT nCount = ::recv( sThread.hSocket, ( CHAR* )byBuffer, 2048, 0 );
if ( nCount == SOCKET_ERROR )
{
APPTRACE( "read error(%d)\n", WSAGetLastError( ) );
break;
}
// the first packet
content HTTP header
// the other was
not. :)
if ( bFirstPacket )
{
CHAR szHead[ 5 ] = { 0 };
memcpy( szHead, byBuffer, 4 );
if ( stricmp( ( CHAR* )szHead, "http" ) == 0 )
{
pTemp = ( BYTE* )strstr( ( CHAR* )byBuffer, "\r\n\r\n" );
pTemp += 4;
nCount -= ( INT )( pTemp - byBuffer );
}
else
{
APPTRACE( "error\n" );
break;
}
}
bFirstPacket = FALSE;
bComplete = sThread.pPiece->OnReadData( pTemp, nCount );
///////////////////////////////////////////////////////////////////
// one piece download
over...
// break for(;;) loop and
ready get a next download piece
///////////////////////////////////////////////////////////////////
if ( bComplete )
{
break;
//::WSASetEvent( sThread.wEvent );
}
}
else if ( wNetEvent.lNetworkEvents & FD_CLOSE )
{
if ( wNetEvent.iErrorCode[ FD_CLOSE_BIT ] )
{
APPTRACE( "FD_CLOS_ERROR -- %d\n", wNetEvent.iErrorCode[
FD_READ_BIT ] );
break;
}
APPTRACE( "wNetEvent.lNetworkEvents & FD_CLOSE\n" );
break;
}
//::WSAResetEvent( sThread.wEvent );
}
}
/////////////////////////////////////////////////////////////////////////
// is have download piece or empty ?
/////////////////////////////////////////////////////////////////////////
if ( bComplete )
{
bContinue = sThread.pHost->OnPieceComplete( sThread );
}
else
{
bContinue = sThread.pHost->OnPieceError( sThread );
}
}
while( bContinue );
//////////////////////////
// if bContinue was TRUE means have download piece remain
// jump to head and from HTTP server to get piece data.
// NOTE: sThread's piece info was replace.
APPTRACE( "OnExecute Over...\n" );
::WSACloseEvent( sThread.wEvent );
::closesocket( sThread.hSocket );
return 0;
}};
.
- Follow-Ups:
- Re: About WSAEventSelect Model Problem.
- From: Michael K. O'Neill
- Re: About WSAEventSelect Model Problem.
- From: madmanahong
- Re: About WSAEventSelect Model Problem.
- Prev by Date: Re: on accept just occurs at the first time
- Next by Date: Re: About WSAEventSelect Model Problem.
- Previous by thread: on accept just occurs at the first time
- Next by thread: Re: About WSAEventSelect Model Problem.
- Index(es):
Relevant Pages
|