Форум АНТИЧАТ

Форум АНТИЧАТ (https://forum.antichat.xyz/index.php)
-   С/С++, C#, Delphi, .NET, Asm (https://forum.antichat.xyz/forumdisplay.php?f=24)
-   -   Сокет и получение данных (https://forum.antichat.xyz/showthread.php?t=42939)

[NiGHT]DarkAngel 23.06.2007 22:47

Сокет и получение данных
 
Народ,я решил попробывать свои силы и сделать качалку фаилов )) , создал сокет, отправляю запрос http серверу на получение фаила,теперь вопрос е подскажите,где можно почитать про получение данных из сокета и сохрание на диске,как убрать из сокета ответ http сервера? Пишу на С++

Зарание благодарен

ЗЫ ногами сильно не бить,я только учусь ))

GoreMaster 23.06.2007 22:54

Цитата:

ответ http сервера?
.data
file db "C:\test.exe",0
url db "your_host/file",0
.code
invoke URLDownloadToFile, NULL,ADDR url ,ADDR file ,0,NULL
в wininet.dll функция
http://www.wasm.ru/article.php?article=socketvssocket
З.Ы.:на каком языке пишешь?

slesh 23.06.2007 23:18

2 GoreMaster Он укзал что пишет на С++. Твой пример хорошь, но на нем него нельзя нацепить прогрессбар ;)

2 [NiGHT]DarkAngel Ты из соката через recv читай сначала данные во временный буфер. КОгда уже пройдут все HTTP заголовки. то потом начинай читать и сразу писать в файл.

NetMan 24.06.2007 06:19

Вот сабж: Создание простого HTTP-клиента

je0n 24.06.2007 12:30

http://forum.web-hack.ru/index.php?showtopic=6328

Тебе еще потребуются знание http-протокола. Юзай гугл. Вкратце: сначала посылаешь GET-запрос, затем получаешь в цикле через recv получаешь инфу. Что-то вроде этого:
Код:

char buf_in[10];
int x;
char page_text[50000];    //тут будет храниться все, что получаешь

        x=recv(sock,buf_in,sizeof(buf_in)-1,0);
        while(x>0)       
        {
                buf_in[x]=0;
                lstrcat(page_text,buf_in);
//                printf(buf_in);
                x=recv(sock,buf_in,sizeof(buf_in)-1,0);
        }

Ну и еще пример функции. Я писал ее, чисто чтобы получать код страницы, а не файла. Но суть-то одна и таже. Ты и файл ей получишь.

Код:

char* GETRequest(char* server,char* page)
{
        WSADATA sock_info;
        int err=WSAStartup(MAKEWORD(2,0),&sock_info);
        if(err==SOCKET_ERROR)
        {
                printf("WSAStartup error");
                return 0;
        }
        int sock;
        struct sockaddr_in sa;
        struct hostent* h;
        char page_text[50000];
        char buf_in[10];
        char buf_out[500];
        int x;
        sa.sin_family=AF_INET;
        sa.sin_port=htons(80);
        h=gethostbyname(server);
        memcpy(&sa.sin_addr,h->h_addr_list[0],h->h_length);
        sock=socket(AF_INET,SOCK_STREAM,0);
        if(connect(sock,(sockaddr*)&sa,sizeof(sa))<0)
        {
                printf("connect() error");
                return 0;
        }
        lstrcpy(buf_out,"GET ");                  //Составляем GET-запрос
        lstrcat(buf_out,page);
        lstrcat(buf_out," HTTP/1.0\r\n");
        send(sock,buf_out,lstrlen(buf_out),0);
        lstrcpy(buf_out,"Host: izobilnik.ru\r\n");
        send(sock,buf_out,lstrlen(buf_out),0);
        lstrcpy(buf_out,"Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, */*\r\n");
        send(sock,buf_out,lstrlen(buf_out),0);
        lstrcpy(buf_out,"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)\r\n\r\n"); //заголовок User-Agent:
        send(sock,buf_out,lstrlen(buf_out),0);
        lstrcpy(page_text,"");
        x=recv(sock,buf_in,sizeof(buf_in)-1,0);
        while(x>0)
        {
                buf_in[x]=0;
                lstrcat(page_text,buf_in);
//                printf(buf_in);
                x=recv(sock,buf_in,sizeof(buf_in)-1,0);
        }
        closesocket(sock);
        return page_text;
}

пример использования:
Код:

char p[50000];
lstrcpy(file,GETRequest("izobilnik.ru","/yourfile.zip"));

по идее в p, должен быть ответ от сервера, вместе с файлом. Если файл большой, то увеличь значение в 50000

[NiGHT]DarkAngel 24.06.2007 13:23

всем спасибо,завтро сдам экзамен и буду пробывать )

[NiGHT]DarkAngel 26.06.2007 21:46

Так я научился получать данные и псиать в фаил )) , подскажите плз еще немножко,как убрать из фаила ответ Http-сервера ?или где почитать ))

Зарание благодарен

KEZ 27.06.2007 06:44

Цитата:

создал сокет, отправляю запрос http серверу на получение фаила,теперь вопрос е подскажите,где можно почитать про получение данных из сокета и сохрание на диске,как убрать из сокета ответ http сервера? Пишу на С++
получение данных из сокета - recv() и recvfrom(), тебе нужна первая
сохранение на диске - запиши в файл. например CreateFile(), WriteFile(), CloseHandle()
убрать ответ сервера - обреж все до двух \r\n подряд и дальше сохраняй.

как я понимаю ты сначала записываешь в файл все, что вернул сервер. если да то пошли с нами долбаться и гонять по вене. на*** сохранять в файл ответ сервера? получаешь ответ, пока не встретятся \r\n два раза. затем читаешь в буффер скажем по 5кб данных и сохраняешь в файл. если надо эстетичнее - находи Content-Length: X и считывай X после переносов. если ещё эстетичнее - InternetOpen(), HttpOpenRequest(), HttpSendRequest() и так далее. например из illusion

Код:


DWORD Download( LPSTR server, LPSTR path, LPSTR local )
{
        HINTERNET hInternet = _InternetOpen( TEXT("Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.5a) Gecko/20030728 Mozilla Firebird/0.6.1"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 );

        if (!hInternet)
                return 5;

    HINTERNET hConnect =
                _InternetConnect(
                hInternet,
                TEXT( server ),
                INTERNET_DEFAULT_HTTP_PORT,
                NULL, NULL, INTERNET_SERVICE_HTTP, 0, (LPDWORD)1u );

        if (!hConnect)
                return 6;

        HINTERNET hRequest = _HttpOpenRequest( hConnect, TEXT( "GET" ), TEXT( path ), NULL, NULL, 0, INTERNET_FLAG_KEEP_CONNECTION, (LPDWORD)1 );
        if (!hRequest)
                return 7;

        BOOL bSend = _HttpSendRequest( hRequest, NULL, NULL, NULL, NULL );
        if (!bSend) return 8;
 
        /* delete old file */
        _DeleteFile( local );

        /* create new */
        HANDLE hFile = _CreateFile( local, GENERIC_WRITE, NULL, NULL, CREATE_NEW, NULL, NULL );
        if (hFile == INVALID_HANDLE_VALUE) return 9;

        DWORD dwBytesRead, dwBytesWrite;
        BYTE szData[1024];
        BYTE ret = 0;

        for (;;)
        {
                if (!Opt_HTTP_Download.started)
                {
                        ret = 1;
                        break;
                }

                BOOL bRead = _InternetReadFile( hRequest, szData, sizeof( szData ) - 1, &dwBytesRead );
                Opt_HTTP_Download.filesize += 1024; //dwBytesRead;

                if (!bRead || !dwBytesRead) break;

                szData[dwBytesRead] = 0;
                if (!_WriteFile( hFile, szData, dwBytesRead, &dwBytesWrite, NULL )
                        || !dwBytesWrite) break;
        }

        _CloseHandle( hFile );
        _InternetCloseHandle( hRequest );
        _InternetCloseHandle( hConnect );
        _InternetCloseHandle( hInternet );

        if (ret) return 255; else return 1;
}

_funcname заменяй на funcname
всякие if (!Opt_HTTP_Download.started) уберай

je0n, пиздец ты друг накатал ***ни)
может будет по байту запрос составлять и отсылать по байту?
так нельзя?
sprintf( request, "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", path, host );
send( s, request, strlen( request ), 0 );

Цитата:

lstrcat(page_text,buf_in);
*** ты из файла, в котором встречаются нулевые байты, запишешь таким образом данные

Цитата:

char page_text[50000];
угу, а потом return page_text ... да, все-таки некоторым больше подойдет делфи

Цитата:

char p[50000];
lstrcpy(file,GETRequest("izobilnik.ru","/yourfile.zip"));
ну а тут вообще без комментариев

Цитата:

2 [NiGHT]DarkAngel Ты из соката через recv читай сначала данные во временный буфер. КОгда уже пройдут все HTTP заголовки. то потом начинай читать и сразу писать в файл.
Гениальный совет кодера. Не даром у тебя написано "asm+delphi". Нахер спрашивается читать сначала в буффер, выделяя -неизвестное- кол-во памяти, а потом в файл, если можно сразу пропустить заголовки и в файл?

PS
кез спит, сейчас разбужу, забыла какая есть ф-ия ещё API там... а. всмысле это нерд пишет) приветик)

_Great_ 27.06.2007 07:41

Цитата:

Сообщение от [NiGHT]DarkAngel
Так я научился получать данные и псиать в фаил )) , подскажите плз еще немножко,как убрать из фаила ответ Http-сервера ?или где почитать ))

Зарание благодарен

Если у тебя с алгоритмикой все в порядке, должен догадаться (RFC почитать что-ли, ну или хз), что данные отделяются от заголовка последовательностью \r\n\r\n
Ищи эти 4 байта в ответе сервера.

ЗЫ. это если протокол 1.0. У протокола 1.1 там свои выкрутасы еще есть.

Цитата:

Сообщение от KEZ
на*** сохранять в файл ответ сервера? получаешь ответ, пока не встретятся \r\n два раза. затем читаешь в буффер скажем по 5кб данных и сохраняешь в файл. если надо эстетичнее - находи Content-Length: X и считывай X после переносов.

Ну.. для протокола хттп 1.0 достаточно просто сохранять тупо всё, пока сокет не закроют на сервере.
Для протокола 1.1 - там передается отдельно длина запроса, и после передачи всего тела сокет не закрывается, так что если этого не учесть, твоя прога повиснет, когда получит все данные, и отвиснет только после разрыва соединения по тайм-ауту

KEZ 27.06.2007 09:09

Цитата:

Ну.. для протокола хттп 1.0 достаточно просто сохранять тупо всё, пока сокет не закроют на сервере.
Для протокола 1.1 - там передается отдельно длина запроса, и после передачи всего тела сокет не закрывается, так что если этого не учесть, твоя прога повиснет, когда получит все данные, и отвиснет только после разрыва соединения по тайм-ауту
ну это ясно, только мы пишем в заголовке HTTP/1.0 и все путем)

slesh 27.06.2007 14:46

2 Kez млин. конечно нужен временный буфер куда читать.
я просто навренео не правильно выразился. я имел в виду троковую переменну. в которую читать данные и искать конец Http заголовка.

sn0w 28.06.2007 15:01

Http заголовок завершается двойным Crlf. дальше идут данные.

[NiGHT]DarkAngel 01.07.2007 12:20

Так вроде чето получилось написать,хтмл странички принимаю без проблем,а вот с остальным rar, exe и тд. как то не важно,куда то теряются данные при передачи ((

Если не трдуно посмотрите пожалйуста исходник и моно носом ткнуть что и где неправильно))

Ногами сильно не бить , я только учусь и в этой проге куча всяких недостатков и багов,но все ранво зарание всем спасибо за все )


Код:

//---------------------------------------------------------------------------

#include <vcl.h>
#include <iostream.h>
#include <conio.h>
#include <winsock2.h>
#include <stdlib.h>
#include <stdio.h>
#pragma hdrstop

//---------------------------------------------------------------------------

class my_socket
{
public:
SOCKET client;
my_socket();
~my_socket();

int error() {cout << "!!! Owu6ka !!!" << WSAGetLastError() << endl; return 1;}
int sends(char *byf,SOCKET client);
};

my_socket::my_socket()
{
WSAData w;
int error=WSAStartup (0x0202, &w);
if (error)
 {
 cout << "Neizvestna9 owubka :( " <<endl;

 }
 if (w.wVersion != 0x0202)
 { // íå òà âåðñèÿ ñîêåòîâ!
WSACleanup (); // âûãðóæàåì  ws2_32.dll

 }

cout << "Rabotaet konstructor" << endl;
}

my_socket::~my_socket()
{

WSACleanup();
cout << "Rabotaet destructor " << endl;
}

int my_socket::sends(char *buff, SOCKET client)
{
int rVal=0;

rVal = send(client,buff,strlen(buff),0);

    if(rVal == SOCKET_ERROR)
    {
        cout <<"Failed send()"<<endl;
        return 1;
    }
    else
    {cout << " Yspewno peredalos' " << endl;}
    return 0;
}

#pragma argsused
int main(int argc, char* argv[])
{
cout << "Na4alo rabotu programmu" << endl;
my_socket my;
SOCKET s;
sockaddr_in target;


s = socket (AF_INET, SOCK_STREAM, 0); // Ñîçäà¸ì ñîêåò

target.sin_family = AF_INET;          // ñåìåñòâî àäðåñîâ - Èíòåðíåò
target.sin_port = htons (80);        // ïîðò ñåðâåðà
target.sin_addr.s_addr = inet_addr ("127.0.0.1");
//target.sin_addr.s_addr = inet_addr ("87.224.128.10");  // IP-àäðåñ ñåðâåðà
int rVal=0;
rVal=connect(s,(LPSOCKADDR)&target, sizeof(target));
 if(rVal==SOCKET_ERROR)
    {
        cout << "Failed connection" << endl;
        return 1;
    }
  else {cout << " Socket yspewno soedenils9" << endl;}

my.sends("GET http://127.0.0.1/files/my.txt HTTP/1.0\r\n\r\n",s);
my.sends("User-Agent: myDownload 0.1\r\n\r\n",s);
my.sends("Accept: */*\r\n\r\n",s);
my.sends("Host: 127.0.0.1 \r\n\r\n",s);
//my.sends("Connection: close\r\n\r\n",s);


char buf_in[8];
int x;
char page_text[190000];    //òóò áóäåò õðàíèòüñÿ âñå, ÷òî ïîëó÷àåøü
FILE *tele;
if ((tele = fopen("my.txt","w+b")) == NULL)
{
 cout << " Open file error " <<endl;
 getch();
 return -1;
}

x=recv(s,buf_in,sizeof(buf_in)-1,0);

while(x>0)
{
 buf_in[x]=0;
 lstrcat(page_text,buf_in);
 //cout << buf_in;
 //getch();
 x=recv(s,buf_in,sizeof(buf_in)-1,0);
}

cout << endl << "strlen(page_text) = " << strlen(page_text) << endl;

int i;
for (i=0;i<strlen(page_text);i++)
{
 if ((page_text[i]=='\r') && (page_text[i+1]=='\n') && (page_text[i+2]=='\r')&& (page_text[i+3]=='\n'))
  {
  cout << "Est' taka9 stroka i = " << i << endl;  break;
  }

}
int p,b,q;
p=i+4;

q=(strlen(page_text)-p);
char *stroka;
cout << "p = " << p<< endl;
cout << "strlen = " << q << endl;
for (b=p;b<strlen(page_text);b++)
{
cout << "b= " <<b << endl;
stroka=&(page_text[b]);
fwrite(stroka,strlen(stroka),1,tele); break;
}
    closesocket(s);
    my.~my_socket();
getch();
        return 0;
}
//---------------------------------------------------------------------------


KEZ 01.07.2007 12:52

Цитата:

lstrcat(page_text,buf_in);
Б**** сколько ещё раз написать тебе что lstrcat - присоединяет СТРОКУ. Строка заканчивается нулевым символом. А у тебя содержимое рар или ехе может иметь что угодно, в том числе и нули.

И ещё, мне кажется что тебе рановато использовать КЛАССЫ. Ещё и такие бессмысленные как в данном случае. Спрашивается - нахера они тебе тут нужны?

NetMan 06.07.2007 18:59

Sorry 2 all...
Вот накатал скачивание при помощи класса CInternetFile библиотеки MFC.
Код:

void DownloadFile(LPCSTR pstrURL,LPCSTR lpszFileName)
{
        CInternetSession inetSession;
        CInternetFile *inetFile = (CInternetFile *) inetSession.OpenURL(pstrURL, 1, INTERNET_FLAG_TRANSFER_BINARY | INTERNET_FLAG_DONT_CACHE);
        CFile file(lpszFileName,CFile::modeCreate | CFile::modeWrite | CFile::typeBinary);

        char buf[8192];
        DWORD dwBytesRead;
        while (dwBytesRead=inetFile->Read(buf, sizeof(buf)))
                file.Write(buf, dwBytesRead);
       
        inetFile->Close();
        delete inetFile;
        inetSession.Close();
}


A110ut 06.07.2007 19:29

Цитата:

скачивание при помощи класса CInternetFile библиотеки MFC
NetMan, может проще взять Download Master ?

[NiGHT]DarkAngel, не поддавайся на провокации. еб*аш Свой довнлоадер пока не заработает. если не получается по другому, то нужно учится и на своих ошибках..

da_ff 07.07.2007 00:19

с начала не читал так что есди не попаду в тему то просто не обращайте внимания

FILE *out;
while(x=ecv(s,buf_in,sizeof(buf_in)-1,0))
{
buf_in[x]=0;
fwrite(buf_in,x,1,out);
}

че то типа того

Ni0x 07.07.2007 00:34

da_ff, исправь ecv на recv

KEZ 07.07.2007 02:40

Я не знаю даже. Может вам картинку с комиксом нарисовать надо или под музыку песню написать где рассказывается на китайском что strcat() прикрепляет строку к строке а не массив байт к массиву байт и что через MFC делать скачивание файла - все равно что через 3DS MAX рисовать точку на экране?

_Great_ 07.07.2007 09:20

Блин, стоит только отойти, уже флейма разведут на Н страниц. Таких тем в инете полно! Исходников тоже!
На крайняк если ТС ничего не найдет (вероятность менее 1%), то я потом выложу в паблик Antichat Web Tool, где скачивание страницы реализовано через чистые сокеты.

В двух словах:

Код:

SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
SOCKADDR_IN sa = {0};
sa.sin_family = AF_INET;
HOSTENT* phe = gethostbyname("google.ru");
*(DWORD*)&sa.sin_addr.s_addr = *(DWORD*)phe->h_addr_list[0];
sa.sin_port = htons(80);
connect( s, &sa, sizeof(sa) );

const int bsize = 1024*1024;  // 1 megabyte
char *buffer = new char[bsize];
wsprintf( buffer, "GET http://google.ru/ HTTP/1.0\r\nHost: google.ru\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 );
char *body = strstr( buffer, "\r\n\r\n" );
body += 4; // strlen of \r\n\r\n

// now buffer contains full response, body contains only response body

delete buffer;

Цитата:

Вот накатал скачивание при помощи класса CInternetFile библиотеки MFC.
Скачка файла через MFC - из пушки по воробьям

Тема закрыта


Время: 12:01