Модераторы: feodorv
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> HTTP запросы, пользуя WinSock 
:(
    Опции темы
bugmenot
Дата 7.11.2006, 22:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 135
Регистрация: 3.7.2006

Репутация: нет
Всего: 1



Вот небольшая програма, которая должна читать страницу forum.vingrad.ru/index.php (код в конце поста)
Вроде работает, но приходит по чистям (с этим проблем нет), и в каждой части на верх добавляется такая фигня:
Цитата

HTTP/1.1 200 OK
Transfer-Encoding: chunked
Date: Tue, 07 Nov 2006 19:03:35 GMT
Content-Type: text/html; charset=windows-1251
Expires: Tue, 07 Nov 2006 19:03:35 GMT
Cache-Control: no-cache, must-revalidate, max-age=0
Server: Apache/2.0.54 (Debian GNU/Linux) FrontPage/5.0.2.2635 mod_python/3.1.3 Python/2.3.5 PHP/5.1.6-0.dotdeb.2 mod_ssl/2.0.54 OpenSSL/0.9.7e mod_webapp/1.2.0-dev mod_perl/1.999.21 Perl/v5.8.4
X-Powered-By: PHP/5.1.6-0.dotdeb.2
Set-Cookie: CookieIp=[Тут мой IP]; expires=Mon, 23-Oct-2034 17:36:32 GMT
Set-Cookie: proforumsession_id=ab38f5aae89468353035152e63b3eef9; path=/; domain=.vingrad.ru
Pragma: no-cache
Via: 1.1 NetCache-DSL-MED-Stack2 (NetCache NetApp/6.0.3P2D2)

1eba

Че это такое? Какой у этой фигни формат? Искал инфу про нее, не нашел

Ну и еще вопрос
Код

    char sendbuf[] = 
        "GET /index.php HTTP/1.1\n"
        "Accept: */*\n"
        "Host: forum.vingrad.ru\n"
        "\n";

^ Что сюда еще можно/нужно писать?

Вот код:
Код

#include <stdio.h>
#include "winsock2.h"

#pragma comment(lib, "WSOCK32.lib")

void main()
{
    WSADATA wsaData;

    if(WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR)
    {
        printf("Error at WSAStartup()\n");

        getchar();
        return;
    }

    SOCKET ConnectSocket;

    ConnectSocket=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(ConnectSocket == INVALID_SOCKET)
    {
        printf("Error at socket(): %ld\n", WSAGetLastError());
        WSACleanup();

        getchar();
        return;
    }

    sockaddr_in clientService;

    clientService.sin_family = AF_INET;
    clientService.sin_addr.s_addr = inet_addr("62.75.204.171");
    clientService.sin_port = htons(80);

    if(connect(ConnectSocket, (SOCKADDR*)&clientService, sizeof(clientService)) == SOCKET_ERROR)
    {
        printf("Failed to connect.\n");
        WSACleanup();

        getchar();
        return;
    }

    int bytesSent;
    int bytesRecv = 0;
    char sendbuf[] = 
        "GET /index.php HTTP/1.1\n"
        "Accept: */*\n"
        "Host: forum.vingrad.ru\n"
        "\n";
    char recvbuf[1000] = "";

    bytesSent = send(ConnectSocket, sendbuf, strlen(sendbuf), 0);
    printf("Bytes Sent: %ld\n", bytesSent);
    if(bytesSent == SOCKET_ERROR)
    {
        printf("Error at send()\n");
        closesocket(ConnectSocket);
        WSACleanup();

        getchar();
        return;
    }

    while(bytesRecv != SOCKET_ERROR)
    {
        bytesRecv = recv(ConnectSocket, recvbuf, 1000, 0);
        if(bytesRecv == 0 || bytesRecv == WSAECONNRESET)
        {
            printf("Connection Closed.\n");
            break;
        }
        printf( "Bytes Recv: %ld\n", bytesRecv );
    }

    if(bytesRecv == SOCKET_ERROR)
        printf("recv failed: %d\n", WSAGetLastError());

    closesocket(ConnectSocket);
    WSACleanup();

    getchar();

    return;
}


Большое спасибо
--------------------
доска объявленийвсе о горных велосипедах 
PM MAIL   Вверх
ptr
Дата 9.11.2006, 14:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 661
Регистрация: 31.5.2006
Где: Новосибирск

Репутация: 9
Всего: 14



Цитата(bugmenot @  8.11.2006,  01:11 Найти цитируемый пост)
Че это такое? Какой у этой фигни формат? Искал инфу про нее, не нашел

Это заголовок ответа сервера. Если бы ты читал описание протокола, то знал бы, что это такое.

Цитата(bugmenot @  8.11.2006,  01:11 Найти цитируемый пост)
^ Что сюда еще можно/нужно писать?

Всё согласно спецификации протокола smile . Кстати везде в запросе надо писать не просто "\n", а "\r\n".

Описание протокола можешь найти тут.


--------------------
Единственный способ определить границы возможного - это выйти за эти границы, в невозможное.
Артур Кларк.
PM MAIL ICQ   Вверх
bugmenot
Дата 11.11.2006, 17:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 135
Регистрация: 3.7.2006

Репутация: нет
Всего: 1



Вот написал такую прогу, которая записывает forum.vingrad.ru/index.php в test.html (внизу)
Функцию ApplyHtmlToFile написал сам, и наверно там очень много ошибок, но вроде работает =)
Скажите пожалуйста все ли ОК, что можно исправить, оптимизировать итд.

И еще вопрос:
Если я хочу сохранить страницу в памяти, как лучше всего это сделать?
Идея юзать LocalReAlloc сто раз мне не нравится, плиз посоветуйте

Спасибо! =)

Код

#include <stdio.h>
#include <winsock2.h>

#pragma comment(lib, "WSOCK32.lib")

SOCKET ConnectToHttpServer(LPTSTR lpHostName, WORD wHost);
int ApplyHtmlToFile(HANDLE hFile, LPTSTR lpBuffer, int dwBufferSize, BOOL *bWroteHeaders, int iLeftToWrite);

void main()
{
    SOCKET Socket;

    int bytesSent;
    int bytesRecv;
    char sendbuf[] = 
        "GET /index.php HTTP/1.1\r\n"
        "Host: forum.vingrad.ru\r\n"
        "\r\n";
    char recvbuf[1000];

    HANDLE hFile;
    DWORD dwNumberOfBytesWritten;

    BOOL bWroteHeaders=0;
    int iLeftToWrite=0;


    Socket=ConnectToHttpServer("forum.vingrad.ru", 80);
    if(!Socket)
    {
        getchar();
        return;
    }

    hFile = CreateFile("test.html", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if(hFile == INVALID_HANDLE_VALUE)
    {
        WSACleanup();
        printf("Could not create test.html\n");
        getchar();
        return;
    }

    bytesSent = send(Socket, sendbuf, strlen(sendbuf), NULL);
    if(bytesSent == SOCKET_ERROR)
    {
        printf("Error at send()\n");
        closesocket(Socket);
        WSACleanup();

        return;
    }

    printf("Bytes Sent: %ld\n", bytesSent);

    WriteFile(hFile, "<!--\r\n", sizeof("<!--\r\n")-1, &dwNumberOfBytesWritten, NULL);

    do
    {
        bytesRecv = recv(Socket, recvbuf, 1000, 0);
        if(bytesRecv == 0 || bytesRecv == WSAECONNRESET)
        {
            printf("Connection Closed.\n");
            break;
        }

        printf("Bytes Recv: %ld\n", bytesRecv);
        iLeftToWrite=ApplyHtmlToFile(hFile, recvbuf, bytesRecv, &bWroteHeaders, iLeftToWrite);
    }
    while(bytesRecv != SOCKET_ERROR);

    CloseHandle(hFile);

    if(bytesRecv == SOCKET_ERROR)
        printf("recv failed: %d\n", WSAGetLastError());

    closesocket(Socket);
    WSACleanup();

    getchar();
}

SOCKET ConnectToHttpServer(LPTSTR lpHostName, WORD wHost)
{
    WSADATA wsaData;
    SOCKET ConnectSocket;
    sockaddr_in ClientService;
    hostent *RemoteHost;

    if(WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR)
    {
        printf("Error at WSAStartup()\n");
        return NULL;
    }

    ConnectSocket=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(ConnectSocket == INVALID_SOCKET)
    {
        printf("Error at socket(): %ld\n", WSAGetLastError());
        WSACleanup();
        return NULL;
    }

    ClientService.sin_family = AF_INET;
    RemoteHost = gethostbyname(lpHostName);
    ClientService.sin_addr.s_addr = (DWORD)RemoteHost->h_addr;
    ClientService.sin_port = htons(wHost);

    if(connect(ConnectSocket, (SOCKADDR*)&ClientService, sizeof(ClientService)) == SOCKET_ERROR)
    {
        printf("Failed to connect.\n");
        WSACleanup();
        return NULL;
    }

    return ConnectSocket;
}

int ApplyHtmlToFile(HANDLE hFile, LPTSTR lpBuffer, int dwBufferSize, BOOL *bWroteHeaders, int iLeftToWrite)
{
    DWORD dwNumberOfBytesWritten;

    if(!*bWroteHeaders)
    {
        for(int i=0; i<dwBufferSize-3; i++)
            if(*(LPDWORD)(lpBuffer+i)==0x0A0D0A0D)
            {
                i+=2;
                WriteFile(hFile, lpBuffer, i, &dwNumberOfBytesWritten, NULL);
                WriteFile(hFile, "-->\r\n", sizeof("-->\r\n")-1, &dwNumberOfBytesWritten, NULL);
                lpBuffer+=i+2;
                dwBufferSize-=i+2;
                *bWroteHeaders=TRUE;
                break;
            }

        if(!*bWroteHeaders)
        {
            WriteFile(hFile, lpBuffer, dwBufferSize, &dwNumberOfBytesWritten, NULL);
            return 0;
        }
    }

    while(TRUE)
    {
        if(!dwBufferSize)
            return iLeftToWrite;

        if(!iLeftToWrite)
        {
            do
            {
                iLeftToWrite*=0x10;
                iLeftToWrite+=(*lpBuffer>='a')?(*lpBuffer-'a'+10):(*lpBuffer-'0');
                lpBuffer++;
                dwBufferSize--;
            }
            while(*(LPWORD)lpBuffer!=0x0A0D);
            lpBuffer+=2;
            dwBufferSize-=2;

            if(!iLeftToWrite)
                return NULL;
        }

        if(iLeftToWrite>=dwBufferSize)
        {
            WriteFile(hFile, lpBuffer, dwBufferSize, &dwNumberOfBytesWritten, NULL);
            return iLeftToWrite-dwBufferSize;
        }
        else
        {
            WriteFile(hFile, lpBuffer, iLeftToWrite, &dwNumberOfBytesWritten, NULL);
            lpBuffer+=iLeftToWrite+2;
            dwBufferSize-=iLeftToWrite+2;
            iLeftToWrite=0;
        }
    }
}


Присоединённый файл ( Кол-во скачиваний: 18 )
Присоединённый файл  get_vingrad.rar 13,29 Kb
--------------------
доска объявленийвсе о горных велосипедах 
PM MAIL   Вверх
ptr
Дата 13.11.2006, 09:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 661
Регистрация: 31.5.2006
Где: Новосибирск

Репутация: 9
Всего: 14



Цитата(bugmenot @  11.11.2006,  20:47 Найти цитируемый пост)
Функцию ApplyHtmlToFile написал сам, и наверно там очень много ошибок, но вроде работает =)

Как-то плохо работает. Программа на ней падает постоянно.

Код

SOCKET ConnectToHttpServer(LPTSTR lpHostName, WORD wHost)
{
     ...
     return NULL;
     ...
}

Не хорошо в качестве SOCKET возвращать NULL.

Везде, где в main обрабатываешь ошибки забываешь делать closesocket.


--------------------
Единственный способ определить границы возможного - это выйти за эти границы, в невозможное.
Артур Кларк.
PM MAIL ICQ   Вверх
bugmenot
Дата 13.11.2006, 16:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 135
Регистрация: 3.7.2006

Репутация: нет
Всего: 1



Цитата(ptr @  13.11.2006,  09:38 Найти цитируемый пост)
Как-то плохо работает. Программа на ней падает постоянно.

В смымле вылетает? У меня нормально работает
Цитата(ptr @  13.11.2006,  09:38 Найти цитируемый пост)
Не хорошо в качестве SOCKET возвращать .

Почему не хорошо? NULL это ноль - 0, т.е. произошла ошибка
Цитата(ptr @  13.11.2006,  09:38 Найти цитируемый пост)
Везде, где в main обрабатываешь ошибки забываешь делать closesocket. 

Спасибо
Цитата(bugmenot @  11.11.2006,  17:47 Найти цитируемый пост)

И еще вопрос:
Если я хочу сохранить страницу в памяти, как лучше всего это сделать?
Идея юзать LocalReAlloc сто раз мне не нравится, плиз посоветуйте

smile
--------------------
доска объявленийвсе о горных велосипедах 
PM MAIL   Вверх
ptr
Дата 13.11.2006, 19:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 661
Регистрация: 31.5.2006
Где: Новосибирск

Репутация: 9
Всего: 14



Цитата(bugmenot @  13.11.2006,  19:57 Найти цитируемый пост)
В смымле вылетает? У меня нормально работает

В прямой смысле. В 100% запусков происходит Access Violation.

Цитата(bugmenot @  13.11.2006,  19:57 Найти цитируемый пост)
Почему не хорошо? NULL это ноль - 0, т.е. произошла ошибка

Да NULL - ноль, но кто тебе сказал, что для SOCKET это допустимо. Некоторые компиляторы на NULL будут ругаться. С SOCKET лучше работать как с непрозрачным типом, в твоём случае, например, можешь вернуть тот же INVALID_SOCKET.

Цитата(bugmenot @  13.11.2006,  19:57 Найти цитируемый пост)
И еще вопрос:Если я хочу сохранить страницу в памяти, как лучше всего это сделать?Идея юзать LocalReAlloc сто раз мне не нравится, плиз посоветуйте

Так или иначе тебе придётся в памяти создавать некоторый буфер и там хранить содержимое. Ну и соответсвенно уметь изменять размеры буфера.


--------------------
Единственный способ определить границы возможного - это выйти за эти границы, в невозможное.
Артур Кларк.
PM MAIL ICQ   Вверх
PyAlexey
Дата 12.2.2007, 17:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 57
Регистрация: 19.9.2006
Где: Россия, Нижний Но вгород

Репутация: нет
Всего: 7



Помогите разобраться.

Я полный NULL в C++, да не программист вообще. Но вот решил поэксперементировать, написав простенький downloader.

Короче, нашёл в инете пример работы с сокетами. Но, аналогично проблеме у автора топика, сервер в случае html выдаёт сначала заголовок, а потом сам текст; а в случае бинарного файла - только заголовок.

Как я понимаю, здесь проблема либо в формировании запроса, либо в чтении из сокета.

Запрос:
Код

    strcpy(query, "GET /");
    strcat(query, http_path);
    strcat(query, " HTTP/1.0\nHost: ");
    strcat(query, http_host);
    strcat(query, "\nUser-agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
    strcat(query, "\nAccept: */*\n\n");


Чтение из сокета:
Код

    int size = 1024*1024;
    char *result=(char*)malloc(size);
    strcpy(result,"");
    char *result_ptr=result;

    while (cnt != 0 && size > 0){
        cnt = recv(s, result_ptr, sizeof(size), 0);
        if (cnt > 0){
            result_ptr += cnt;
            size -= cnt;
        }
    }
    *result_ptr = 0;
    // в result результат

Как мне получить текстовый и бинарный файл без заголовка?

P.S. Просьба не отсылать к чтению спецификации - мне пока этого не требуется.
PM   Вверх
ptr
Дата 14.2.2007, 15:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 661
Регистрация: 31.5.2006
Где: Новосибирск

Репутация: 9
Всего: 14



1. Показывай ответы сервера.
2. Не забывай про \r\n.


--------------------
Единственный способ определить границы возможного - это выйти за эти границы, в невозможное.
Артур Кларк.
PM MAIL ICQ   Вверх
PyAlexey
Дата 14.2.2007, 17:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 57
Регистрация: 19.9.2006
Где: Россия, Нижний Но вгород

Репутация: нет
Всего: 7



Если запрашивать страницу, то всё нормально, за исключением ненужного мне заголовка.
Код

Conecting to 127.0.0.1...Ok
GET / HTTP/1.0
Host: localhost
User-agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
Accept: */*

HTTP/1.1 200 OK
Date: Wed, 14 Feb 2007 13:54:50 GMT
Server: Apache/1.3.33 (Win32) PHP/5.1.2
Connection: close
Content-Type: text/html

<html>
<head>
...
</body>
</html>

Если запрашивать бинарный файл, то выдаётся только заголовок - и всё, программа удачно завершается.
Код

Conecting to 127.0.0.1...Ok
GET /favicon.ico HTTP/1.0
Host: localhost
User-agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
Accept: */*

HTTP/1.1 200 OK
Date: Wed, 14 Feb 2007 13:54:06 GMT
Server: Apache/1.3.33 (Win32) PHP/5.1.2
Last-Modified: Tue, 23 Nov 2004 07:35:00 GMT
ETag: "0-13e-41a2e824"
Accept-Ranges: bytes
Content-Length: 318
Connection: close
Content-Type: image/x-icon
X-Pad: avoid browser bug

Если использовать \r\n вместо \n и \n\n, то всё останавливается на чтении из сокета... ((

P.S. Вот пример, который я использовал.

Это сообщение отредактировал(а) PyAlexey - 14.2.2007, 17:08
PM   Вверх
ptr
Дата 15.2.2007, 18:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 661
Регистрация: 31.5.2006
Где: Новосибирск

Репутация: 9
Всего: 14



Цитата(PyAlexey @  14.2.2007,  20:04 Найти цитируемый пост)
за исключением ненужного мне заголовка.

Этот заголовок очень даже нужный. Он содержит много полезной информации.

Цитата(PyAlexey @  12.2.2007,  20:47 Найти цитируемый пост)
Как мне получить текстовый и бинарный файл без заголовка?

Никак. Ты сначала должен получить заголовок, проанализировать его (распарсить, посмотреть нет ли ошибок и т.д.) и уже потом получать всё остальное.

Цитата(PyAlexey @  14.2.2007,  20:04 Найти цитируемый пост)
и всё, программа удачно завершается.

Посмотри в отладчике (ну или обычным printf) что происходит в данный момент (например что возвращает recv).

Цитата(PyAlexey @  14.2.2007,  20:04 Найти цитируемый пост)
Если использовать \r\n вместо \n и \n\n,

Перевод строки должен быть \r\n.

Цитата(PyAlexey @  14.2.2007,  20:04 Найти цитируемый пост)
Вот пример, который я использовал.

Интересно знать в какой раз автор работает с сокетами, да и вообще программирует smile . Такого плохого кода я давно не видел. Лучше найди нормальный пример работы с сокетами. Не обязательно связанный с HTTP, просто отсылка/приём текста. Или посмотри в этом разделе. Тут были вполне сносные примеры работы с HTTP, по крайней мере лучше, чем на CodeNet smile .

PyAlexey, а что ты хочешь написать то?

Это сообщение отредактировал(а) ptr - 15.2.2007, 19:03


--------------------
Единственный способ определить границы возможного - это выйти за эти границы, в невозможное.
Артур Кларк.
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.1377 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.