|
..вообще должно и по 1.0
|
Posted by: Delimiter on November 30, 2002 at 06:32:52
Posters Details: [195.14.158.39], X-Forwarded 4: [] [Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; Win 9x 4.90; COM+ 1.0.2204)]
In Reply to: как собрать файл пришедший по HTTP/1.1? Posted by: name on November 29, 2002 at 18:58:30
# Суть такая
# Мне надо, чтобы моя программа скачивала с веб cервера мой файл myfile, например с mine.narod.ru,
#
# По HTTP/1.0 почему-то не получается ни с одного известного мне сервера
#
..вообще должно и по 1.0
# "GET /myfile HTTP/1.0 \r\n\r\n"
....здесь не экономь перестраховайся(не как не мог это слово прална написать..определялось как нецензурщина))) и дай полный урл...на дефаулт надейся но сам не плошай
# возвращает не найдено
#
# А если добавить в запрос дополнительные поля
# GET /myfile HTTP/1.0 \nHost: mine.narod.ru\n\r\n\r\n
....ну тут ты и дефаулт определил ))
# то сервер отвечает 200 (Найден)
# но уже по HTTP/1.1
# А как собрать эти чанки, я не знаю,
# Программа должна быть очень маленькой,
# может кто знает алгоритм декодирования?
#
# Или может быть как то можно указать чтобы
# файл не дробился вовсе?
нельзя указать о том чтобы файл не дробился...
либо ты должен просто иметь полный контроль над
TCP/IP стэком ))) что в видоуз проста затруднительно проще переписать ви32эс длл))))
А вообще совет ЗАПУСКАЙ СНИФЕР и задайся целью делать лучче чем IE)))
ТАК ))...
мой работающий на 2 десятках машин код))
m_path=CString((char *)my_path);
sockl = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
setsockopt(sockl, SOL_SOCKET, SO_REUSEADDR, (const char*)&bReuse, sizeof(BOOL)); //bReuse обьяви как true
memset ((char *)&clnt_sin, '\0',sizeof(clnt_sin));
/* clnt_sin.sin_family = AF_INET;
clnt_sin.sin_addr.s_addr = INADDR_ANY;
clnt_sin.sin_port =htons(myport); //тут можно и не использовать постоянный))
int m=bind (sockl, (struct sockaddr *)&clnt_sin,sizeof(clnt_sin));
if(m!=0)
{
m_mes += "Bind error..."; m_mes += "\r\n";
::PostMessage((HWND)param,DATE_UPDATE,0,0);
binderror(); // здесь у меня пищит))
return 0; // все это в нитке крутится просто вывожу результаты по "ходу"
}
else */
{
memset ((char *)&srv_sin, '\0',sizeof(srv_sin));
srv_sin.sin_family = AF_INET;
if(isproxy==1)
{ // тут должно быть понятно готовлюсь соединиться с прокси
srv_sin.sin_addr.s_addr= inet_addr((char *)IPproxy);
srv_sin.sin_port =htons(proxyport);
}
else
{
srv_sin.sin_addr.s_addr= inet_addr((char *)IPstr);
srv_sin.sin_port =htons(sport);// а здесь готовлюсь к конекту на прямую
}
int u=file2.Open((LPCTSTR)m_path,
CFile::modeCreate|CFile::modeWrite|CFile::typeBinary,&e); // ну тут готовлю файл для записи слитого
m=connect (sockl,(struct sockaddr *) &srv_sin, sizeof(srv_sin));
if(m==0 && u!=0)
{
connectinfo();
strcpy((char *)strtosend,"GET ");
if(isproxy==1)
{
strcat((char *)strtosend,"http://");
strcat((char *)strtosend,(char *)IPstr); // здесь мне проста лень поэтому леплю прямо АЙПИ))
strcat((char *)strtosend,":");
strcat((char *)strtosend,itoa(sport,prbuf,10));
}
strcat((char *)strtosend,(char *)askstr);
strcat((char *)strtosend," HTTP/1.1\r\nAccept: */*\r\nPragma: no cache\r\nUser-Agent: ");
strcat((char *)strtosend,(char *)custname);
strcat((char *)strtosend,"\r\nHost: ");
strcat((char *)strtosend,(char *)IPstr);
strcat((char *)strtosend,":");
strcat((char *)strtosend,itoa(sport,prbuf,10));
strcat((char *)strtosend,"\r\n");
if(isproxy==1)
;// strcat((char *)strtosend,"Proxy-Connection: Keep-Alive\r\n");
strcat((char *)strtosend,"\r\n");
int w=send(sockl,(char *)strtosend,strlen((char *)strtosend),0);
entr1=1; entr2=1;
// ну все что выше основная HTTP лабуда
if(w!=strlen((char *)strtosend))
{
m_mes += "Error send! \r\n";
shutdown(sockl,SD_BOTH);
closesocket(sockl);
::PostMessage((HWND)param,DATE_UPDATE,0,0);
::PostMessage((HWND)param,STOP_HTTP,0,0);
file2.Close();
return 0;
}
time_t start, finish;
time( &start );
m_mes = "Starting ..."; m_mes += "\r\n";
::PostMessage((HWND)param,DATE_UPDATE,0,0);
//тута просто готовимся к тяжелой жизни))
do
{
ioctlsocket(sockl,FIONREAD,&arg);
if(arg!=0)
{
inquire=new char[arg+2];
for(int i=0;i<arg+2;i++)
*(inquire+i)=0;
int len=recv(sockl,inquire,arg,0);
if((pt=strstr(inquire,"Content-Length:"))!=0)
{
m_mes += "Find Content\r\n";
::PostMessage((HWND)param,DATE_UPDATE,0,0);
pt+=15;
for(int i=0; *(pt+i)!=0x0d;i++) ;
*(pt+i)=0;
length=atoi(pt);
*(pt+i)=0x0d;
entr1=0;
if(u!=0)
if((pt=strstr(inquire,"</HTML>"))!=0)
{//мне этого условия достаточно ты же могешь и по контент длинне)
incld=1;
}//ЗДЕСЬ ПРОИЗОШЛО НЕПРЕДВИДЕЕНОЕ ))) ВСЕ ПРИШЛО ОДНИМ ПАКЕТОМ КАК ПРАВИЛО -ЭТО НЕ ТАК
file2.Write(inquire,arg);
}
delete[] inquire;
}
//Sleep(1);
time( &finish );
if(difftime(finish,start)>400)
{// ну тут сам понимаешь ..пытаемся вывалиться СЕГОДНЯ НЕ НАШ ДЕНЬ....придем чуть позже ))
m_mes += "Error! Big delay\r\n";
shutdown(sockl,SD_BOTH);
closesocket(sockl);
file2.Close();
::PostMessage((HWND)param,DATE_UPDATE,0,0);
::PostMessage((HWND)param,STOP_HTTP,0,0);
return 0;
}
} while (entr1!=0);
m_mes = "Starting ..."; m_mes += "\r\n";
m_mes += "File name to save : ";
m_mes += m_path; m_mes += "\r\n";
::PostMessage((HWND)param,DATE_UPDATE,0,0);
if(u!=0 && incld!=1)
{
time( &start );
do
{
ioctlsocket(sockl,FIONREAD,&arg);
if(arg!=0)
{
inquire=new char[arg+2];
for(int i=0;i<arg+2;i++)
*(inquire+i)=0;
int len=recv(sockl,inquire,arg,0);
file2.Write(inquire,arg);
length-=len;
if(length<25)
{
entr2=0;
}
if(strstr(inquire,"</HTML>")!=0)
{
entr2=0;
}
delete[] inquire;
}
time( &finish );
if(difftime(finish,start)>300)
{
file2.Close();
m_mes += "Error! Big delay\r\n";
shutdown(sockl,SD_BOTH);
closesocket(sockl);
::PostMessage((HWND)param,DATE_UPDATE,0,0);
::PostMessage((HWND)param,STOP_HTTP,0,0);
Sleep(5);
return 0;
}
} while (entr2!=0);
file2.Close();
shutdown(sockl,SD_BOTH);
Sleep(5);
closesocket(sockl);
m_mes += "Have got..\r\n";
::PostMessage((HWND)param,DATE_UPDATE,0,0);
}
else
if(incld==1)
{
file2.Close();
shutdown(sockl,SD_BOTH);
Sleep(5);
closesocket(sockl);
m_mes += "Have got..\r\n";
::PostMessage((HWND)param,DATE_UPDATE,0,0);
//::PostMessage((HWND)param,STOP_HTTP,0,0);
}
}
else
{
file2.Close();
connecterror();
m_mes += "Error! No connection\r\n";
m_mes+=itoa(WSAGetLastError(),prbuf,10);
m_mes += "-error! \r\n";
shutdown(sockl,SD_BOTH);
Sleep(5);
closesocket(sockl);
::PostMessage((HWND)param,DATE_UPDATE,0,0);
::PostMessage((HWND)param,STOP_HTTP,0,0);
return 0;
}
}
+=================+
ВТОРОЙ СПОСОБ ОБПИСАННЫЙ ВО ВСЯКХ ДОКАХ
и так же "рабочий"... лень стирать свои ремированные ошибки ...так что без купюрррр)))
for(;flagwait!=0;)
Sleep(5);
if(strlen((char *)my_url)>3)
m_url=CString((char *)my_url);
m_path=CString((char *)my_path);
// создаём переменную session и открываем сессию ANDY
CInternetSession session( _T( "Delimiter" ), PRE_CONFIG_INTERNET_ACCESS );
// создаём переменную pServer класса CHttpConnection
CHttpConnection* pServer = NULL;
// создаём переменную pFile класса CHttpFile
CHttpFile* pFile = NULL;
/*
Обратите внимание, что все запросы к функциям членам WinInet классов включены в блок программы TRY.
Это сделано так, потому что при соединении с каким либо URL есть риск неправильной ссылки,
особенно, когда Вы полагаете, что пользователь сам печатает URL.
Другая проблема - времена ожидания, которые возникают, когда требуемый URL в настоящее время
неспособен обслужить подключение.
Так же обработка WinInet исключений, которые представлены в классе
CInternetException, является важной частью создания Internet приложения под MFC.
*/
try
{
// функция AfxParseURL получает данные с указанного URL ( у нас m_url ) об сервере,
// объекте, типе сервиса и порте
if ( AfxParseURL( m_url, dwServiceType, strServerName, strObject, nPort ) == 0 )
{
::PostMessage((HWND)param,STOP_HTTP,0,0);
delete[] mytempbuf;
// _endthreadex( 1);
//AfxEndThread( 1 );
// выход из функции OnButtonConnect()
//_endthread();
return 0;
}
// вывод данных о сервере
m_mes = "";
m_mes += "Server Name = ";
m_mes += (CString)strServerName; m_mes += "\r\n";
m_mes += "Object Name = ";
m_mes += (CString)strObject; m_mes += "\r\n";
m_mes += "Port = ";
itoa( nPort, temp, 10 );
m_mes += (CString)&temp[0]; m_mes += "\r\n";
// UpdateData( FALSE );
::PostMessage((HWND)param,DATE_UPDATE,0,0);
// Устанавливаем подключение по HTTP протоклолу.
pServer = session.GetHttpConnection( strServerName, nPort );
// посылаем запрос об объекте ( strObject )
pFile = pServer->OpenRequest(
CHttpConnection::HTTP_VERB_GET, strObject, NULL, 1, NULL, NULL,
INTERNET_FLAG_EXISTING_CONNECT | INTERNET_FLAG_NO_AUTO_REDIRECT | INTERNET_FLAG_DONT_CACHE
);
// Добавляем заголовок к HTTP запросу
pFile->AddRequestHeaders( _T( "Accept: */*\r\nUser-Agent: Delimiter\r\n" ) );
// посылаем запрос
pFile->SendRequest( );
DWORD dwRet; // переменная для хранения кода состояния
pFile->QueryInfoStatusCode( dwRet ); // записываем код состояния в dwRet
// вывод данных
m_mes += "The HTTP GET returned a status code of ";
itoa( dwRet, temp, 10 );
m_mes += (CString)&temp[0]; m_mes += "\r\n";
CString strHeader; // переменная для хранения полученного заголовока запроса
pFile->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF, strHeader); // записываем заголовок в strHeader
// вывод данных
m_mes += "Header = ";
m_mes += strHeader;
::PostMessage((HWND)param,DATE_UPDATE,0,0);
// UpdateData( FALSE );
// если код состояния не равен 200, то выходим из функции
if( dwRet != 200 )
{ m_mes += "thread terminate!";
::PostMessage((HWND)param,STOP_HTTP,0,0);
delete[] mytempbuf;
session.Close( );
return 0;
}
// ----------------------------------------------------------
// проверка выбора файла для записи
m_mes += "Starting download the file."; m_mes += "\r\n";
if( m_path == "" )
{
m_mes += "Error! No file to save. Choese the file.";
m_mes += "\r\n";
//UpdateData( FALSE );
// ::PostMessage(hWnd,DATE_UPDATE,0,0);
// Sleep(5);
session.Close( );
::PostMessage((HWND)param,STOP_HTTP,0,0);
delete[] mytempbuf;
// _endthread();
return 0;
}
else
{
m_mes += "File name to save : ";
m_mes += m_path; m_mes += "\r\n";
::PostMessage((HWND)param,DATE_UPDATE,0,0);
//UpdateData( FALSE );
}
// открываем файл для записи в двоичном формате ( CFile::typeBinary ) !!!
file2.Open((LPCTSTR)m_path,
CFile::modeCreate|CFile::modeWrite|CFile::typeBinary);
int allRead = 0; // переменная для хранения общего числи считанных байт
int nRead = pFile->Read( strBody, 1024 ); // считываем первые 1024 байта в буфер.
// переменная nRead хранит количество
// считанных байт
allRead += nRead; // обновляем общее число считанных байт
// вывод данных
m_mes += "Loading ";
itoa( nRead, temp, 10 );
m_mes += (CString)&temp[0]; m_mes += " bytes"; m_mes += "\r\n";
::PostMessage((HWND)param,DATE_UPDATE,0,0);
// UpdateData( FALSE );
// записываем буфер из nRead байт в файл
file2.Write( strBody, nRead );
// цикл считывания, пока nRead не будет равняться нулю
while ( nRead > 0 )
{
nRead = pFile->Read( strBody, 1024 );
if( nRead != 0 )
{
m_mes += "Loading ";
itoa( nRead, temp, 10 );
m_mes += (CString)&temp[0]; m_mes += " bytes"; m_mes += "\r\n";
file2.Write( strBody, nRead );
allRead += nRead;
::PostMessage((HWND)param,DATE_UPDATE,0,0);
// UpdateData( FALSE );
}
}
// вывод данных
m_mes += "\r\n";
m_mes += "Total bytes = ";
itoa( allRead, temp, 10 );
m_mes += &temp[0]; m_mes += "\r\n";
::PostMessage((HWND)param,DATE_UPDATE,0,0);
//UpdateData( FALSE );
file2.Close(); // закрываем файл
pFile->Close(); // закрываем Internet файл
pServer->Close(); // закрываем сервер
m_mes += "Download is complete !!!"; m_mes += "\r\n";
::PostMessage((HWND)param,DATE_UPDATE,0,0);
//UpdateData( FALSE );
}
catch ( CInternetException* pEx )
{
// Если произошла ошибка в WinInet
// вывод ошибки
char szErr[1024];
pEx->GetErrorMessage( szErr, 1024 );
strcpy((char *)status,"Error: ( ");
m_mes += "Error: ( ";
itoa( int(pEx->m_dwError), temp ,10 );
strcat((char *)status,temp);
m_mes += (CString)&temp[0];
m_mes += " ) ";
strcat((char *)status," ) ");
m_mes += (CString)&szErr[0]; m_mes += "\r\n";
strcat((char *)status,&szErr[0]);
::PostMessage((HWND)param,DATE_UPDATE,0,0);
// UpdateData( FALSE );
pEx->Delete( ); // удаление переменной класса CInternetException
if ( pFile != NULL )
delete pFile; // закрываем Internet файл
if ( pServer != NULL )
delete pServer; // закрываем сервер
// session.Close( ); // закрываем сессию
flaghttp=0;
delete[] mytempbuf;
::PostMessage((HWND)param,STOP_HTTP,0,0);
// AfxEndThread( 1 );
Sleep(50);
return 0;
// _endthread();
//mycritfl=1;
}
if ( pFile != NULL )
delete pFile; // закрываем Internet файл
if ( pServer != NULL )
delete pServer; // закрываем сервер
session.Close( ); // закрываем сессию
НО ДЛЯ ЭТОГО СПОСОБА СРАЗУ СКАЖУ ))) У МЕНЯ ИСКЛЮЧЕНИЯ НЕ ПОЗВОЛЯЛИ УБИТЬ ЭТУ НИТКУ ))
Follow Ups:
|
|