Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Сети > Помогите, проблема с сокетами и icq!


Автор: AK84 28.8.2009, 06:05
Люди добрые, помогите, вторые сутки не могу разобраться в чём дело.

Задача такая - коннект и логин к ICQ через HTTP прокси.
QIP коннектится нормально, ну или выдаёт, что много подключений с данного IP, в общем - работает нормально.

Пытаюсь повторить то же самое и получаю такой вот прикол:
Коннекчусь к прокси, делаю запрос на коннект к login.icq.com:5190
От сайта аськи приходит запрос на логин
Отсылаю пакет с данными...

И тут всё, с моей стороны сокет закрывается. Без ответа от сервера аськи.
Перешерстив кучу форумов, нашёл только, что проблема может быть в том, что сокет закрывается раньше времени. Но почему??? Помогите. Блин, вторые сутки не сплю  smile 

Пробовал один к одному посылать то, что шлёт QIP (пакеты один в один), потом прверял wiresharkom - от меня и QIP'a приходят одинаковые пакеты, но сервак квипу отвечает, а у меня сокет закрывается  smile 

Без прокси всё работает прекрасно.

Вот код :

Код

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

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

      //----------------------
      // The sockaddr_in structure specifies the address family,
      // IP address, and port of the server to be connected to.
      sockaddr_in clientService; 
      clientService.sin_family = AF_INET;
      clientService.sin_addr.s_addr = inet_addr( "200.226.137.11" );   //      прокси
      clientService.sin_port = htons( 80 );


      //----------------------
      // Connect to server.

      int iMode = 0;
      ioctlsocket(ConnectSocket, FIONBIO, (u_long FAR*) &iMode);

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

      //----------------------
      // Declare and initialize variables.
      int bytesSent;
      int bytesRecv = SOCKET_ERROR;
      char sendbuf[] = "CONNECT login.icq.com:5190 HTTP/1.0\r\nUser-Agent: Mozilla/4.08 [en] (WinNT; U)\r\n\r\n";
      char recvbuf[512] = "";

      //----------------------
      // Send and receive data.
      bytesSent = send( ConnectSocket, sendbuf, strlen(sendbuf), 0 );
      printf( "Bytes Sent: %ld\n", bytesSent );

///   Проверяем, что прокси прислал ответ HTTP/1.0 200 OK, что он приконнектился
      while (true) {
        bytesRecv = recv( ConnectSocket, recvbuf, 512, 0 );
        if (bytesRecv>0 && (recvbuf[9]=='2')) {
            break;
        } else {
            printf("%s\n",recvbuf);
            return -1;
        }
      }

//  Ждём от сервера аськи пакет с приглашением к логину
      while (true) {
        bytesRecv = recv( ConnectSocket, recvbuf, 512, 0 );
        if (bytesRecv>0 && (recvbuf[0]==0x2A || recvbuf[9]=='2')) {
            break;
        } else {
            printf("%s\n",recvbuf);
            return -1;
        }
      }
      cout << "conn request\n";
      DG=0;
      DG=recvbuf[2]*256;
      DG+=recvbuf[3];

///  формируем пакет для отправки с логином и паролем
        char outBuf[512];
        CString outData[20];

        CString tStr2,roast_pwd,pas,UIN;

        CString ClientIDName=L"ICQ Inc. - Product of ICQ (TM).2003b.5.56.1.3916.85";
        long ClientIDNumber=0x010A;
        long ClientMjVer=5;
        long ClientMnVer=56;
        long ClientLsVer=1;
        long ClientBldNumber=3916;
        long ClientDistrb=85;
        CString ClientLanguage=L"en";
        CString ClientCountry=L"uk";

        UIN="123456789";
        pas="12345678";
        tStr2=pas;
        byte roast_arr[]={0xF3, 0x26, 0x81, 0xC4, 0x39, 0x86, 0xDB, 0x92, 0x71, 0xA3, 0xB9, 0xE6, 0x53, 0x7A, 0x95, 0x7C };
        for (int i=0;i<pas.GetLength();i++) {
            roast_pwd.AppendChar(tStr2[i] ^ roast_arr[i]);
        }

        // cli_ident
        outData[0]=L"BLANK-d-4=1";
        outData[1].Format(L"TLV-0001-s=%s",UIN);
        outData[2].Format(L"TLV-0002-s=%s",roast_pwd);
        outData[3].Format(L"TLV-0003-s=%s",ClientIDName);
        outData[4].Format(L"TLV-0016-d-2=%d",ClientIDNumber);
        outData[5].Format(L"TLV-0017-d-2=%d",ClientMjVer);
        outData[6].Format(L"TLV-0018-d-2=%d",ClientMnVer);
        outData[7].Format(L"TLV-0019-d-2=%d",ClientLsVer);
        outData[8].Format(L"TLV-001A-d-2=%d",ClientBldNumber);
        outData[9].Format(L"TLV-0014-d-4=%d",ClientDistrb);
        outData[10].Format(L"TLV-000F-s=%s",ClientLanguage);
        outData[11].Format(L"TLV-000E-s=%s",ClientCountry);

        int bts;
        int ts;

// Функция GeneratePacket собирает пакет для отправки.
// Работает ПРАВИЛЬНО, потому что без прокси всё работает

        bts=GeneratePacket(outData, outBuf, 12, L"FLAP");
        send( ConnectSocket, outBuf, bts, 0 );

// Если оставить while(true), то просто висит бесконечно ничего не получая.
// Если так, как есть, то сразу же выход
// На этом этапе получается, что сокет УЖЕ закрыт :(
//
// Это тестовая программка, в основной программе через CAsyncSocket я получаю OnClose
// после отправки пакета с логином и паролем, тоесть то же самое 
        while( bytesRecv == SOCKET_ERROR ) {
//        while (true) {
            bytesRecv = recv( ConnectSocket, recvbuf, 512, 0 );
            if (bytesRecv>0) {
                printf("%s\n",recvbuf);
            }
        }

      WSACleanup();



HEEEEEEELP, плиииииииз !!!!
Срочно надо.... На работе съедят скоро  smile

Добавлено через 4 минуты и 6 секунд
Или дайте, пожалуйста нормальный класс для работы с ICQ, который умеет через прокси.
Перерыл весь Гугл - не нашёл :(

Вернее нашёл только для C#, а мне надо для C++

Автор: andrew_121 28.8.2009, 06:19
Не думаю что писать реализацию протокола целесообразно. Так как все уже написано.
тут: http://ru.wikipedia.org/wiki/OSCAR
а так же, в составе qutim(http://qutim.org/) есть отличная реализация этого протокола на С++.

Автор: AK84 28.8.2009, 06:31
Писать реализацию смысл есть, потому что во-первых своё - это свое smile, а во-вторых то, что мне попадалось, меня не устраивает. Либо не умеет работать через прокси, либо так наворочено, что чёрт ногу сломит.

Qutim, скачал, сейчас ковыряю...

Добавлено через 6 минут и 7 секунд
###, в Qutim разобрался, но мне нужен класс свой, оттуда выдирать что-то к себе - повеситься проще или написать своё, чем я и пытаюсь заниматься.

Мож у кого-то есть какие-то наработки - киьте плиииз.

Автор: andrew_121 28.8.2009, 08:34
Цитата(AK84 @  28.8.2009,  06:31 Найти цитируемый пост)
в Qutim разобрался, но мне нужен класс свой, оттуда выдирать что-то к себе - повеситься проще или написать своё, чем я и пытаюсь заниматься.

Думаете получится лучше?

Автор: AK84 28.8.2009, 08:53
Думаю, что получится, надо только вот с этой проблемой разобраться с проксями, потому что без проксей всё работает нормально и написано достаточно много и, главное, что всё работает. Я не нашёл классов для работы с аськой, а народу их ищет много, значит мой класс будет кому-то ещё кроме меня нужен. Допишу - выложу в паблик, пусть люди пользуются.

ПОМОГИТЕ РАЗОБРАТЬСЯ С ПРОБЛЕМОЙ, ПРОЕКТ СТОИТ!!!  smile 

Автор: andrew_121 28.8.2009, 13:30
оффтоп:
Цитата(AK84 @  28.8.2009,  08:53 Найти цитируемый пост)
а народу их ищет много

Странно. Все под носом. Чего ищут то?

Автор: AK84 28.8.2009, 13:48
Интересно, что "всё"??

Дай ссылку на класс, который я прямо сейчас себе к проекту подключу и он будет работать без расковыривания кода класса, чтобы адаптировать его под себя.

Я работаю в MSVS 2005

Автор: andrew_121 28.8.2009, 20:57
Цитата(AK84 @  28.8.2009,  13:48 Найти цитируемый пост)
чтобы адаптировать его под себя.

Вот: http://dev.aol.com/aim/oscar все в одном.

Автор: AK84 28.8.2009, 21:35
Спасибо, сейчас гляну....

О результатах напишу позже smile

Автор: Олег2005 28.8.2009, 22:40
Общепринятый порт для HTTP-прокси - 8080

Автор: AK84 30.8.2009, 06:52
Да порт без разницы.
Это я себе искалку для прокси написал, она мне и нашла тот, что в примере.
Проблема, кстати, так и осталась. Даже не в самой аське дело. Просто я так понимаю, что это я неправильно с сокетами работаю. То, что сокет закрывается ДО того как приходят данные - это 100%.
Вопрос в том, как это побороть?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)