About WSAEventSelect Model Problem.

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



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;
}};

.



Relevant Pages

  • Re: why use ftp if http provides the same services???
    ... > download it from a ftp site or http.. ... > html.eg.word,spreadsheet file) from http server and ftp server.? ...
    (comp.lang.java.programmer)
  • Re: Assembly conversion to Pocket Pc format
    ... string strfilename = ... for .NET assemblies, i.e. it is simply passing them through unmodified. ... rather I want to download from HTTP or HTTPS. ...
    (microsoft.public.dotnet.framework.compactframework)
  • Re: HTTP Download complete detect using TCP sniffer
    ... its HTML have been received. ... HTTP parsing" would tell me the HTTP download is complete please? ... When the request is sent you start ...
    (microsoft.public.win32.programmer.networks)
  • Cisco Security Response: Cisco IOS Cross-Site Scripting Vulnerabilities
    ... Cisco Security Response: Cisco IOS Cross-Site Scripting ... Two separate Cisco IOS Hypertext Transfer Protocol (HTTP) cross-site ... scripting vulnerabilities have been reported to Cisco by two ... as purely HTTP Server) and applies to all Cisco products that run ...
    (Bugtraq)
  • Re: Safe Update problem
    ... The reason is that the object being used to fetch the file is the NetWebClient, which is an HTTP client. ... You can replace the SafeDownload procedure in your application with your own version that uses the NetTalk FTP template to fetch the file for you if you have to use FTP to download the file. ... Why I can download file from ftp when I using url without login and password for example: ...
    (comp.lang.clarion)