Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Передача файла по http используя только сокеты

841
26 августа 2007 года
_nic
199 / / 29.07.2006
Выражаясь в общих чертах : обьясните мне пожалуйста как организовать в программе скачивание файл с вебсервера.
Если для файлов с текстовы содержанием все предельно ясно(подключится к вебсерверу,отправить что то типа"GET http://targethost.com/test.txt HTTP/1.0\r\nHost: targethost.com\r\n\r\n",и из полученного текста с помощью strtok и strstr вырезать все нужное).То как быть с другими файлами?
22K
27 августа 2007 года
Pastor
43 / / 16.05.2007
так же... :)
вот только наверное надо указывать MIME
841
27 августа 2007 года
_nic
199 / / 29.07.2006
Цитата: Pastor
так же... :)
вот только наверное надо указывать MIME


Можно попдробней а то тут http://www.lib.ru/WEBMASTER/rfc2068/ о MIME неслова

92
27 августа 2007 года
Тень Пса
2.2K / / 19.10.2006
парсить заголовок ( до \r\n\r\n ) искать Content-Length.

а после \r\n\r\n ловишь столько байт сколько сказано в Content-Length.
355
27 августа 2007 года
<SCORP>
786 / / 21.10.2006
Цитата: Тень Пса
парсить заголовок ( до \r\n\r\n ) искать Content-Length.

а после \r\n\r\n ловишь столько байт сколько сказано в Content-Length.


это если Transfer-Encoding дефолтный ;)
а если нет, то прийдётся декодировать из какого-нибудь chunked

92
29 августа 2007 года
Тень Пса
2.2K / / 19.10.2006
[QUOTE=<SCORP>;208500]это если Transfer-Encoding дефолтный ;)
а если нет, то прийдётся декодировать из какого-нибудь chunked[/QUOTE]
это уже другой вопрос :)
355
29 августа 2007 года
&lt;SCORP&gt;
786 / / 21.10.2006
Цитата: Тень Пса
это уже другой вопрос :)


ну на самом деле да вообще... если не говорить в запросе, что ты умеешь chunked, то приличный сервер его и не пришлёт :)
так что, просто смотришь сколько контента должно быть и столько его и читаешь

240
29 августа 2007 года
aks
2.5K / / 14.07.2006
[QUOTE=<SCORP>;208755]ну на самом деле да вообще... если не говорить в запросе, что ты умеешь chunked, то приличный сервер его и не пришлёт :)
[/QUOTE]
<SCORP>, попробуй скажи это гуглу ))
или у них неприличный сервер?

[QUOTE=<SCORP>;208755]
так что, просто смотришь сколько контента должно быть и столько его и читаешь[/QUOTE]
И рано или поздно натыкаешся на остутвие контента там где он должен быть. )) Есть спецификация протокола, и ее нужно уметь поддерживать. )
841
31 августа 2007 года
_nic
199 / / 29.07.2006
Вот к примеру с помощью этой ф-ции можно получить содержимое текстового файла
Код:
char *httf(char *host=new char[1000],char *uri=new char[1000])
{
WSADATA wsd;
WSAStartup(MAKEWORD(1,1),&wsd);
hostent *h;
char *Ip=new char[150];
h=gethostbyname(host);
sprintf(Ip,"%d.%d.%d.%d",(unsigned char)h->h_addr_list[0][0],(unsigned char)h->h_addr_list[0][1],(unsigned char)h->h_addr_list[0][2],(unsigned char)h->h_addr_list[0][3]);
SOCKADDR_IN ss;
ss.sin_family = AF_INET;
ss.sin_addr.s_addr =inet_addr(Ip);
ss.sin_port = htons(80);
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
connect( s,(sockaddr *)&ss, sizeof(ss) );
const int bsize = 1024*1024;
char *buffer = new char[bsize];
strcpy(buffer,"GET /");
strcat(buffer,uri);
strcat(buffer," HTTP/1.0\r\nHost: ");
strcat(buffer,host);
strcat(buffer,"\r\n\r\n");
send( s, buffer, strlen(buffer), 0 );
int bytes = 0, pos = 0;
do
{
bytes = recv( s, buffer+pos, bsize-pos, 0 );
if( !(bytes>0) )
break;
pos += bytes;
buffer[pos] = 0;
}
while(1);
closesocket( s );
printf(buffer);
char *body = strstr( buffer, "\r\n\r\n" );
body += 4;
WSACleanup();
return(body);
}

Но если с её помощью попытатся получить к примеру *.exe то вернется только 3 буквы : MZP(насколько я понимаю обозначающих тип файла).Хотя Content-Length тмеет правильный размер файла.Так как нужно правильно сформировать запрос а потом принять ответ от сервера,чтобы можно было вытащить из этого ответа содержимое нетекстового файла?
355
01 сентября 2007 года
&lt;SCORP&gt;
786 / / 21.10.2006
а файл ты получаешь полностью :) всё дело в char* сишные строки это последовательность байт, ограниченая нулём. т.е. признаком конца файла является символ с кодом нуль. ну я у себя посмотрел в тотале по F3 первый попавшийся ЕХЕшник... ну четвёртый символ как раз нуль и есть :)
так что данные прочитаны и память под них выделена. просто ты их не видишь.
я думаю, что тебе просто надо писать полученые данные не в char*, а в какой-то поток
841
02 сентября 2007 года
_nic
199 / / 29.07.2006
[QUOTE=<SCORP>;209151]а файл ты получаешь полностью :) всё дело в char* сишные строки это последовательность байт, ограниченая нулём. т.е. признаком конца файла является символ с кодом нуль. ну я у себя посмотрел в тотале по F3 первый попавшийся ЕХЕшник... ну четвёртый символ как раз нуль и есть :)
так что данные прочитаны и память под них выделена. просто ты их не видишь.
я думаю, что тебе просто надо писать полученые данные не в char*, а в какой-то поток[/QUOTE]

Мне раньше не приходилось с тким сталкиватся, можно поподробней?
240
03 сентября 2007 года
aks
2.5K / / 14.07.2006
_nic, собственно зачем ты выводишь в текстовую то впринципе консоль содержимое не текстового файла. Пиши в файл. Потом не нужно дописывать не строкам в конце 0 как это сделанно у тебя. exe файл - это же не срочка большая. Ну и как думаешь что будет если размер файла окажется больше мегабайта? Это я к тому что весь код достаточно корявый и небезопасный. )
92
03 сентября 2007 года
Тень Пса
2.2K / / 19.10.2006
читай в массив byte или сразу в файл пиши... так ты, как минимум, от проблем с нулями отделаешься...
240
03 сентября 2007 года
aks
2.5K / / 14.07.2006
А чем массив byte (кстати нету такого стандартного типа) принципиально отличается от массива char?
просто нужно отделять мух от котлет и не маяться нулями ))
841
04 сентября 2007 года
_nic
199 / / 29.07.2006
Фуух наконец то получилось :D
Код:
void httf(char *host=new char[1000],char *uri=new char[1000])
{
WSADATA wsd;
WSAStartup(MAKEWORD(1,1),&wsd);
hostent *h;
char *buffer2=new char[1024*1024];
char *content;
DWORD n;
char *Ip=new char[150];
h=gethostbyname(host);
sprintf(Ip,"%d.%d.%d.%d",(unsigned char)h->h_addr_list[0][0],(unsigned char)h->h_addr_list[0][1],(unsigned char)h->h_addr_list[0][2],(unsigned char)h->h_addr_list[0][3]);
SOCKADDR_IN ss;
ss.sin_family = AF_INET;
ss.sin_addr.s_addr =inet_addr(Ip);
ss.sin_port = htons(80);
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
connect( s,(sockaddr *)&ss, sizeof(ss) );
const int bsize = 1024*1024;
char *buffer = new char[bsize];
strcpy(buffer,"GET /");
strcat(buffer,uri);
strcat(buffer," HTTP/1.0\r\nHost: ");
strcat(buffer,host);
strcat(buffer,"\r\n\r\n");
send( s, buffer, strlen(buffer), 0 );
int bytes = 0, pos = 0;
do
{
bytes = recv( s, buffer+pos, bsize-pos, 0 );
if( !(bytes>0) )
break;
pos += bytes;
buffer[pos] = 0;
}
while(1);
strcpy(buffer2,buffer);
content=strstr(buffer2,"Content-Length:");
content+=15;
strtok(content,"/n Last");
int size=atoi(content);
closesocket( s );
char *body = strstr( buffer, "\r\n\r\n" );
body += 4;
WSACleanup();
HANDLE f=CreateFile("\\\\.\\C:\\cod\\out.exe",GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,FILE_FLAG_RANDOM_ACCESS, NULL);
WriteFile(f,body,size,&n,NULL);
CloseHandle(f);
delete buffer;
delete buffer2;
delete Ip;
delete host;
delete uri;
}

Спасибо всем кто помог.
240
04 сентября 2007 года
aks
2.5K / / 14.07.2006
Ну косяков то на самом деле не убавилось, а может и прибавилось.

Цитата:

const int bsize = 1024*1024;
char *buffer = new char[bsize];


Что по твоему произойдет при попытке скачать файл больше 1мб?

Цитата:

buffer[pos] = 0;


не правильно, ибо имеет смысл только при работе со строками, но не в общем случае.

Цитата:

HANDLE f=CreateFile("\\\\.\\C:\\cod\\out.exe",GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,FILE_FLAG_RANDOM_ACCESS, NULL);


Зачем так хитро - что бы просто не открыть файл?

Ну и еще кучка маленьких косячков по коду.

92
04 сентября 2007 года
Тень Пса
2.2K / / 19.10.2006
Цитата: aks
просто нужно отделять мух от котлет и не маяться нулями ))


aks, +1. ну я про массив byte так, для приличия сказал ( unsigned char, сам посмотрел, понял что не то ;) ). так что естессна лучше писать в файл сразу :)

 
Код:
const int bsize = 1024*1024;
char *buffer = new char[bsize];
_nic, ну я ш тебе говорил ))) ищи Content-Length и читай столько, сколько там написано :)
240
04 сентября 2007 года
aks
2.5K / / 14.07.2006
Цитата: Тень Пса

_nic, ну я ш тебе говорил ))) ищи Content-Length и читай столько, сколько там написано :)



Не совсем. Content-Length может и не быть. Если его нет - надо уметь и такую ситуацию обрабатывать.
Вот попробуй ссылку:
http://maps.google.com/maps?q=55.751463,37.617273
и глянь какой там Content-Length. А гугл всеже один из очень посещаемых и авторитетных сайтов )

92
04 сентября 2007 года
Тень Пса
2.2K / / 19.10.2006
ну да... ты прав. а как такую ситуёвину обрабатывать? подскажи уж мне, земляку :D я чёт даже и не додумываюсь :(
841
04 сентября 2007 года
_nic
199 / / 29.07.2006
Ая вот ещё что подумал ,как быть при скачивание файлов с бесплатных хостингов типа narod.ru?Ведь там сначала выкидывает страницу ссылкой на запрашиваемый файл.Как в таком случае качать файл,достаточно просто повторить запрос,или надо работать с куками?
92
05 сентября 2007 года
Тень Пса
2.2K / / 19.10.2006
ну дык посмотри, что тебе приходит от narod.ru, если ссылка идет сразу на файл, но по этой ссылке страница, на которой снова ссылка опять на тот же файл, то посмотри - не появились ли куки...

в общем, посмотри что там вообще происходит-то :)
353
05 сентября 2007 года
Nixus
840 / / 04.01.2007
Скорее всего дело в referer'е.
92
05 сентября 2007 года
Тень Пса
2.2K / / 19.10.2006
может быть, для того и говорю пускай посмотрит =)
841
06 сентября 2007 года
_nic
199 / / 29.07.2006
Такой я получаю ответ от сервера
Код:
HTTP/1.1 200 OK
Date: Thu, 06 Sep 2007 19:26:23 GMT
Server: ZX_Spectrum/1997 (Sinclair_BASIC)
Set-Cookie: nuid=1607883821189106783; path=/; expires=Sun, 03-Sep-17 19:26:23 GM
T; domain=.narod.ru
Last-Modified: Mon, 25 Mar 2002 01:27:04 GMT
ETag: "da806-a49a6-3c9e7ce8"
Accept-Ranges: bytes
Content-Length: 674214
Connection: close
Content-Type: video/x-ms-asf

Когда качаю этот файл http://level-0.narod.ru/video/nagasaki.asf
Проблема в том что после компиляции сразуже получаю ошибку по этой строке "strtok(content,"/n Last");"
http://img105.imageshack.us/my.php?image=er2lr0.jpg
прикол в том что эта ошибка получается именно при нажатие F9 , но если запустить собранное приложение то все ОК.Мистика какая то :confused: .Я конечно понимаю что ошибка может быть вызвана ограничением стековой памяти до 1 мб, но мне просто интересно почему невозникает ошибка при запуске уже собранной программы.
ЗЫ:использую борланд С++ билдер 6й версии
355
07 сентября 2007 года
&lt;SCORP&gt;
786 / / 21.10.2006
не /n, а \n
841
07 сентября 2007 года
_nic
199 / / 29.07.2006
[QUOTE=<SCORP>;210015]не /n, а \n[/QUOTE]

Мда,что то я в последнее время невнимательный :(
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог