Модераторы: feodorv, GremlinProg, xvr, Fixin

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Авторизация через winsock 
:(
    Опции темы
I_Am_Rock
  Дата 12.11.2011, 16:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Добрый день.

Прошу мне помочь.  smile 

Стоит задача в авторизации на сайте. Чтобы потом отправлять данные.

Опытным путем было установлено, что через GET сайт не воспринимает данные (логин и пароль).
Т.е. нужно через POST. А значит, насколько я знаю, вариант через URLDownloadToFile не получится.

Т.е. мне нужно использовать winsock. Так ведь?
Но примеры из mdsn и которые я загуглил не освещают эту тему.

Может быть, я плохо искал? Не покажите ли пример, как мне это сделать? Или может быть я вообще ошибаюсь, и тут надо не через winsock?

Пишу в этом разделе, потому что хочу на "чистом" WinAPI.

Буду рад любому ответу.

 smile 
PM MAIL WWW   Вверх
bass
Дата 12.11.2011, 16:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Примеров инете полно как работать с сокетами виндовс ........ стартуешь библиотеку создаешь сокет конектишся к серверу..... Скорее всего на порт 80 который у броузера по умолчанию....... А вот что дальше делать.... Я тебе не подскажу  ... Я бы посмотрел каким нибудь снифером типа тспвьюва.... Как логинится броузер... И сделал бы имитацию того же....
PM MAIL   Вверх
I_Am_Rock
Дата 12.11.2011, 17:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Как работать с сокетами я знаю. Но вот именно как отправлять POST запросы примеров найти не могу. И вот чтобы была авторизация.


Я еще поясню. Я понимаю, что нужно отправлять через send заголовки и тело POST-запроса. Через аддон httpfox я вижу их в браузере Firefox.
Но я не пойму, как связать это потом со вторым запросом. Ведь у браузеров есть куки, сессии, и авторизовавшись я могу работать под своим аккаунтом, а у winsock ведь запросы никак не связаны друг с другом. 

 smile 

Это сообщение отредактировал(а) I_Am_Rock - 12.11.2011, 18:09
PM MAIL WWW   Вверх
I_Am_Rock
Дата 12.11.2011, 22:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Вот такой код. Взял из msdn. И оптимизировал под себя. Вместо site.ru на самом деле настоящий.
Почему-то recv сначала присылала байты, а потом нет (возвращает 0) - пишет ConnectionClosed. Странно. 

Что-нибудь можете сказаться по этому поводу?   smile 


Код

#include <stdio.h>
#include <winsock.h>

#define DEFAULT_BUFLEN 512


int main() {

    //----------------------
    // Declare and initialize variables.
    int iResult;
    WSADATA wsaData;

    SOCKET ConnectSocket;
    struct sockaddr_in clientService;

    int recvbuflen = DEFAULT_BUFLEN;
    char *sendbuf = "POST /auth/ HTTP/1.1/nHost site.ru/nAccept-Charset windows-1251,utf-8/n/nlogin=mylogin&password=mypass";

    char recvbuf[DEFAULT_BUFLEN] = "";

    //----------------------
    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != NO_ERROR) {
        printf("WSAStartup failed with error: %d\n", iResult);
        return 1;
    }

    //----------------------
    // Create a SOCKET for connecting to server
    ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ConnectSocket == INVALID_SOCKET) {
        printf("socket failed with error: %d\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }

    //----------------------
    // The sockaddr_in structure specifies the address family
    clientService.sin_family = AF_INET;
    struct hostent * host_addr = gethostbyname("site.ru");
    clientService.sin_addr.s_addr = *((int*)*host_addr->h_addr_list);
    clientService.sin_port = htons( (unsigned short)80);

    //----------------------
    // Connect to server.
    iResult = connect( ConnectSocket, (SOCKADDR*) &clientService, sizeof(clientService) );
    if (iResult == SOCKET_ERROR) {
        printf( "connect failed with error: %d\n", WSAGetLastError() );
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
  }

    //----------------------
    // Send an initial buffer
    iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
    if (iResult == SOCKET_ERROR) {
        printf("send() failed with error: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }

    printf("Bytes Sent: %d\n", iResult);

    // shutdown the connection since no more data will be sent
    iResult = shutdown(ConnectSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed with error: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }

    // Receive until the peer closes the connection
    do {
        iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
        if ( iResult > 0 )
            printf("Bytes received: %d\n", iResult);
        else if ( iResult == 0 )
            printf("Connection closed\n");
        else
            printf("recv failed with error: %d\n", WSAGetLastError());

    } while( iResult > 0 );


    // cleanup
    closesocket(ConnectSocket);
    WSACleanup();

    return 0;
}


PM MAIL WWW   Вверх
I_Am_Rock
Дата 12.11.2011, 23:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Господа я разобрался с этим, но главный вопрос остался не решенным.

Вот в чем разобрался: в коде выше глупая ошибка (вместо \n стоит /n), еще нужно Content-Type и Content-Lenght. Все добавил, все отлично. Теперь recv возвращает ответ, который надо.

Но главный вопрос не решен. Как сделать, чтобы следующий запрос (т.е. следующий send) я сделал как авторизованный пользователь?


Мое предположение такое: в ответе есть SetCookie: PHPSESSID=большое_число и нужно это как-то "пристегнуть" к следующим SEND'ам.

Скажите, я в правильном направлении?  smile 

Это сообщение отредактировал(а) I_Am_Rock - 12.11.2011, 23:44
PM MAIL WWW   Вверх
I_Am_Rock
Дата 13.11.2011, 00:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Да, все так и есть. Нужно таскать за собой эти куки.

Спасибо всем, вы мне очень помогли.  smile 

Это сообщение отредактировал(а) I_Am_Rock - 13.11.2011, 00:47
PM MAIL WWW   Вверх
I_Am_Rock
Дата 13.11.2011, 14:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Хотя есть еще вопрос!

А что нельзя сразу последовательно выполнять send, recv, send, recv? Почему-то второй send не отрабатывает. И второй recv получает во второй аргумент какую-то белиберду. 
PM MAIL WWW   Вверх
I_Am_Rock
Дата 13.11.2011, 17:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



что, никто не знает? (

send'ы абсолютно идентичны.

Может быть после первого recv нужно что сделать, выполнить какую-то команду.  smile 
PM MAIL WWW   Вверх
volatile
Дата 13.11.2011, 18:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 13
Всего: 85



Цитата(I_Am_Rock @  12.11.2011,  22:14 Найти цитируемый пост)
// Receive until the peer closes the connection
    do {
        iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
        if ( iResult > 0 )
            printf("Bytes received: %d\n", iResult);
        else if ( iResult == 0 )
            printf("Connection closed\n");
        else
            printf("recv failed with error: %d\n", WSAGetLastError());

    } while( iResult > 0 );

Могу предположить, что recv здесь не корректно оформлен.
recv получает 1-ый пакет, здесь все нормально
recv получает 2-ой пакет, А вот здесь он затирает 1-ый пакет. Так как читает его по тому-же адресу что и 1-ый.
Пусть это пример даже из мсдн, он только для демонстрации. Вобще примеры там писали люди далекие от создателей самих функций. Иногда такая фигня проскакивает, диву даешься...

PM MAIL   Вверх
I_Am_Rock
Дата 13.11.2011, 18:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Спасибо за ответ, но это не тот код.  smile  Я уже его передалал и там нет того цикла, т.е. он отрабатывает один раз.

Вот код который у меня сейчас. И в котором у меня ошибка.
Здесь происходит регистрация (1 send). Отправка нужного запроса (2 send). 3 send такой же как и второй, но recv от него возвращает байтовый мусор, да и сам запрос не производит нужных манипуляций на сайте. Я выделил комментарием // !!! эти send, точнее вызов функции (2 раза). 
Причем send не возвращает ошибку. Он как бы выполняется.
Извините за корявость кода! Я потом приведу его в порядок. Просто сейчас не хочу окончательно запутаться, пока понимаю, что да как)

Код

#include <stdio.h>
#include <winsock.h>
 
#define DEFAULT_BUFLEN 512
 
    char * pch1;
    char * pres;
    char * pres1;
 
    int iResult;
    SOCKET ConnectSocket;
    char recvbuf[DEFAULT_BUFLEN] = "";
    char recvbuf1[DEFAULT_BUFLEN] = "";
    int recvbuflen = DEFAULT_BUFLEN;
 
   // это функция, которую вызываю (см. ниже) 2 раза. 1 раз норм, 2 раз нет. :(

int sendandrecv (char* myarg)
{
    char sendall[300];
    char *sendbuf1;
    char *spart3;
 
    sendbuf1 = "POST /profile/do/ HTTP/1.1\nHost: site.ru\nAccept-Charset: windows-1251,utf-8\nContent-Type: application/x-www-form-urlencoded\nContent-Length: 14\nCookie: ";
    spart3 = myarg;
 
    strcpy (sendall, sendbuf1);
    strcat (sendall, pres);
    strcat (sendall, spart3);

    iResult = send( ConnectSocket, sendall, (int)strlen(sendall), 0 );
    if (iResult == SOCKET_ERROR) {
        printf("send() failed with error: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }
 
    iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
    if ( iResult > 0 )
        printf("Bytes received: %d\n", iResult);
}
 
int main() {
 
    WSADATA wsaData;
    struct sockaddr_in clientService;
    char *sendbuf = "POST /auth/ HTTP/1.1\nHost: site.ru\nAccept-Charset: windows-1251,utf-8\nContent-Type: application/x-www-form-urlencoded\nContent-Length: 25\n\nlogin=login&password=pass";
 
    //----------------------
    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != NO_ERROR) {
        printf("WSAStartup failed with error: %d\n", iResult);
        return 1;
    }
 
    //----------------------
    // Create a SOCKET for connecting to server
    ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ConnectSocket == INVALID_SOCKET) {
        printf("socket failed with error: %d\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }
 
    //----------------------
    // The sockaddr_in structure specifies the address family,
    // IP address, and port of the server to be connected to.
    clientService.sin_family = AF_INET;
    struct hostent * host_addr = gethostbyname("site.ru");
    clientService.sin_addr.s_addr = *((int*)*host_addr->h_addr_list);
    clientService.sin_port = htons( (unsigned short)80);
 
    //----------------------
    // Connect to server.
    iResult = connect( ConnectSocket, (SOCKADDR*) &clientService, sizeof(clientService) );
    if (iResult == SOCKET_ERROR) {
        printf( "connect failed with error: %d\n", WSAGetLastError() );
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
  }
 

   // этот сенд для авторизации, с ним все норм. проблем ниже

    iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
    if (iResult == SOCKET_ERROR) {
        printf("send() failed with error: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }
 
    printf("Bytes Sent: %d\n", iResult);
 
        iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
        if ( iResult > 0 ) {
            printf("Bytes received: %d\n", iResult);
            printf("\n%s\n", recvbuf);
 
            pch1 = strstr (recvbuf, "Set-Cookie:");
            pres = strtok (pch1+12, "\n");
            pres1 = pres;
            printf("\n__%s\n", pres);
 
        }
        else if ( iResult == 0 )
            printf("Connection closed\n");
        else
            printf("recv failed with error: %d\n", WSAGetLastError());
 
 
        // !!! ВОТ ЭТИ СЕНДЫ. Точнее вызовы функции, в которой сенды
                        
    sendandrecv("text_zaprosa_1");
        
    sendandrecv("text_zaprosa_2");
 
 
    closesocket(ConnectSocket);
    WSACleanup();
 
    return 0;
}


Это сообщение отредактировал(а) I_Am_Rock - 13.11.2011, 19:00
PM MAIL WWW   Вверх
volatile
Дата 13.11.2011, 19:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 13
Всего: 85



Цитата(I_Am_Rock @  13.11.2011,  18:59 Найти цитируемый пост)
nContent-Length: 14

У вас жестко вбит длина. она всегда 14 байтов?

PM MAIL   Вверх
I_Am_Rock
Дата 13.11.2011, 19:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Пусть этот момент вас не смущает.  smile  Хотя здесь я заменил настоящий адрес сайта на site.ru и настоящий текст запроса, но текст запроса и на самом деле у меня всегда фиксированный (16 символов). И Content-Lenght соответствующий (16).
А здесь я заменил текст запроса, поэтому поменял и content-length на 14.


Вот как так может быть! я вызываю функцию sendandrecv два раза, и в первом случае все нормально работает, а во втором - нет. Ну вот как :(
Может быть если send более чем 1 раз обращает с тем же заголовком, нужно что делать? Какую-то функцию вызывать?  smile 

Порядок такой:
1
send для авторизации - норм
его recv - норм

2
send к определенной странице - норм
его recv - норм

3
такой же send как предыдущий, только с другим текстом - не выполняется на сайте (причем не возвращая SOCKET_ERROR).
его recv - возвращает каракули. либо может просто ничего не возвращает и я пытаюсь вывести указатель "ниначто", что так или иначе указывает на ошибку в recv.



Это сообщение отредактировал(а) I_Am_Rock - 13.11.2011, 19:47
PM MAIL WWW   Вверх
volatile
Дата 13.11.2011, 19:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 13
Всего: 85



I_Am_Rock, попробуйте для каждого нового POST'а открывать новый коннект.
впринципе это так и должно делаться.

PM MAIL   Вверх
I_Am_Rock
Дата 13.11.2011, 21:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Сделал так. Не помогло, уже с ошибкой вылетает программа.

И вот какой момент. Я проставил чуть ли не построчно printf("1") и printf("2") и т.д.  
И я вот что заметил - программа вылетает именно на этой строке в функции sendandrecv 
Код

strcat (sendall, spart3);

До этой строки все выполняется, а потом вылетает.
Причем именно когда эта функция выполняется во второй раз.  smile 


Еще поэкспериментировав, я кажется обнаружил, что проблема в том, что второй функция выполняется, когда send и recv предыдущей функции не завершены. и они мешают друг другу  smile 



Теперь почему-то всегда вторая функция отрабатывает.  smile  smile 

Это сообщение отредактировал(а) I_Am_Rock - 13.11.2011, 21:55
PM MAIL WWW   Вверх
volatile
Дата 13.11.2011, 23:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 13
Всего: 85



Цитата(I_Am_Rock @  13.11.2011,  21:31 Найти цитируемый пост)
программа вылетает именно на этой строке в функции sendandrecv 
код C++
strcat (sendall, spart3);

может буфер переполняется, не проверяли?

PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




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


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

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