Моя программка через Winsock отправляет HTTP-запрос на сервер, мол хочу получить такую-то страницу. Сервер отвечает - нате. Все приходит. Вопрос, а как узнать, что оно пришло полностью? Особенно, когда не указан Content-Length:
| Код | string Answer = ""; vector<in_addr> AddrList; hostent *remoteHost = NULL; DWORD dwError = 0; int i = 0;
WORD wVersionRequested; WSADATA wsaData; int err = 0; wVersionRequested = MAKEWORD( 2, 0 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return string( "Err" ); }
remoteHost = gethostbyname( strHost.c_str() );
if ( remoteHost == NULL ) { dwError = WSAGetLastError(); if ( dwError != 0 ) { if ( dwError == WSAHOST_NOT_FOUND ) { Answer = "Host not found"; return Answer; } else { if (dwError == WSANO_DATA) { Answer = "No data record found"; return Answer; } else { char chErr[1024]; sprintf( chErr, "Function failed with error: %ld\0", dwError ); Answer.append( chErr ); return Answer; } } } } else { i = 0; if ( remoteHost->h_addrtype == AF_INET ) { in_addr adr; while ( remoteHost->h_addr_list[i] != 0 ) { adr.s_addr = *(u_long *) remoteHost->h_addr_list[i++]; AddrList.push_back( adr ); } } else if ( remoteHost->h_addrtype == AF_INET6 ) { Answer = "IPv6 address was returned"; return Answer; } }
if ( AddrList.size() == 0 ) { Answer = "Host does not exist"; return Answer; }
SOCKET s = socket( AF_INET, SOCK_STREAM, IPPROTO_IP ); if ( m_iTime != 0 ) { int sz = sizeof( m_iTime ); if ( setsockopt( s, SOL_SOCKET, SO_RCVTIMEO, (char *)&m_iTime, sz ) != 0 ) { return Answer; }
if ( setsockopt( s, SOL_SOCKET, SO_SNDTIMEO, (char *)&m_iTime, sz ) != 0 ) { return Answer; } }
sockaddr_in dest_addr; dest_addr.sin_family = AF_INET; dest_addr.sin_port = htons( Port ); dest_addr.sin_addr.s_addr = /*inet_addr( strHost.c_str() );*/AddrList[0].s_addr; if ( connect( s, (sockaddr *)&dest_addr, sizeof( dest_addr ) ) == 0 ) { char* buf = new char[BufSize];
int iRes = send( s, strRequest.c_str(), strRequest.length(), 0 ); if ( iRes != SOCKET_ERROR ) { int BytesRec = 0; while ( true ) { int bytes = recv( s, buf, BufSize-1, 0 );
if ( bytes <= 0 ) break; else { BytesRec += bytes; buf[bytes] = '\0'; Answer.append( buf, bytes );
size_t pos1 = Answer.find( "Content-Length: ", 0 ); if ( pos1 != string::npos ) { size_t pos2 = Answer.find( "\r\n", pos1 + 10 ); string strCL = Answer.substr( pos1 + 16, pos2 - pos1 - 16 ); int AnswerContentLength = atoi( Answer.substr( pos1 + 16, pos2 - pos1 - 16 ).c_str() );
pos2 = Answer.find( "\r\n\r\n", 0 ); if ( pos2 != string::npos ) { if ( Answer.size() - pos2 - 4 >= AnswerContentLength ) { break; } } } else { // PROBLEM HERE /*if ( bytes < BufSize-1 ) { break; }*/ } //if ( /*( buf[bytes-1] == '\n' ) || (( buf[bytes-1] == '\0' ))*/ ) //break; } } } } else { //Answer = "Could not connect"; shutdown( s, 2 );
closesocket( s );
WSACleanup();
return Answer; } shutdown( s, 2 );
closesocket( s );
WSACleanup();
|
Ответ не всегда заканчивается какими-то специальными символами, а даже если и заканчивается, нет гарантии, что блок из середины пакета не заканчивается им, и тогда получится что я приму не весь ответ. Так же признаком не является факт, что функция recv выдала нам байт меньше, чем у нас буфер - за время цикла буфер мог просто не заполниться полностью. 0 байт как признак окончания выдается только когда истечет таймаут, что меня абсолютно не устраивает.
|