скрыть

скрыть

  Форум  

Delphi FAQ - Часто задаваемые вопросы

| Базы данных | Графика и Игры | Интернет и Сети | Компоненты и Классы | Мультимедиа |
| ОС и Железо | Программа и Интерфейс | Рабочий стол | Синтаксис | Технологии | Файловая система |



Google  
 

ICQ2000 сделай сам 10




Автор: Alexander Vaga
WEB-сайт: http://icq2000cc.hobi.ru

Одиночество - это когда контакт лист icq грохнулся.

Урок №3

Запрос информации о клиенте,

Поиск клиентов по различным критериям и др.

Итак... Передавать и принимать сообщения уже умеем. На очереди - получение информации о клиентах, которые находятся в списке контактов; а также поиск новых клиентов по различным критериям. Такие запросы к серверу посылаются с помощью все тех же SNAC(15,2). Вспомните, как производится запрос оффлайновых сообщений.

Точно также SNAC(15,2) с типом запроса равным D007 применяется:

  • при всех операциях с Инфо клиентов ( и получение, и обновление своего);
  • при поиске клиентов по имени, по UINу, по E-mailу;
  • при изменении пароля;
  • при удалении UINа из реестра ICQ;
  • при многих других операциях.

Каждая из перечисленных операций определяется подтипом запроса. Приведу обобщенную таблицу SNAC(15,2) для некоторых запросов:

FLAP
Command Start 2A
Channel ID 02
Sequence Number XX XX
Data Field Length XX XX
SNAC (15, 02)
Family ID 00 15
SubType ID 00 02
Flags[0] 00
Flags[1] 00
Request ID 00 XX 00 02 (по ним можно опознать ответ)
TLV (1)
Type 00 01
Length XX XX
Value Length-2
(и что оно тут делает ?)
XX XX XX XX наш UIN
D0 07 тип запроса
XX 00 cookie
(по нему можно/нужно
опознавать ответ)
B2 04 подтип запроса
(B204 - запрос инфо клиента)

Это переменная часть зпроса.
Она определяется подтипом запроса.

Например:

При запросе инфо клиента (B2 04) или при поиске клиента по UINу (1F05) здесь следует разместить запрашиваемый UIN.

При поиске клиента по E-mail (2905) здесь будет помещена строка с искомым адресом.

При поиске по NickName, FirstName, LastName (1505) сюда помещаются соответственно три стоки.

При смене пароля (2E04) здесь будет лишь строка с паролем, а наш UIN сервер и так знает.



Теперь к Delphi-проекту добавлены еще два модуля: UInfo и SUser (User Info & Search User).

Очередные исходники 3-его урока здесь. Т.к. все рассмотренные више запросы практически однотипные, то приведу комментарии только к одному из них. Это будет поиск по NickName, FirstName, LastName:

unit SUser;


procedure TSearchUser.META_Search_User(NN,FN,LN : string);
var p : PPack;
    // промежуточный массив.
    // в нем накапливаются данные TLV(1)
    b : TByteArray;
    i : integer;
begin
     if (NN='')and(FN='')and(LN='') then exit;
     EndOfSearch := false;

     // word(b[0]) - тут будет ненужная длина
     // (но ее надо потом корректно заполнить)
     // а пока переходим к 3-у елементу
     i:=2;

     // вписываем UIN (только СВОЙ - укажем явно,что из модуля Main.pas)
     PLONG(@(b[i]))^ := main.UIN;    inc(i,4);
     // ТИП запроса
     PWORD(@(b[i]))^ := swap($D007);   inc(i,2);
     // придумаем себе COOKIE
     // (можно и по-проще, но в настоящей аське
     // COOKIE имеет такой вид XX00)
     Cookie := random($FF) shl 8;
     PWORD(@(b[i]))^ := swap(Cookie); inc(i,2);
     // ПОДТИП запроса
     PWORD(@(b[i]))^ := swap($1505);   inc(i,2);

     // добавляем три текстовые строки (First, Last, Nick)
     // у AOL новый тип строк наверное :)
     // впереди - длина строки, а в конце #0
     // (что-то одно из них убрали бы)

     // длина строки
     PWORD(@(b[i]))^ := length(FN)+1;  inc(i,2);
     // сама строка FirstName
     MOVE(FN[1],b[i],length(FN));     inc(i,Length(FN));
     // завершающий #0
     PBYTE(@(b[i]))^ := 0;             inc(i,1);

     // LastName
     PWORD(@(b[i]))^ := length(LN)+1;  inc(i,2);
     MOVE(LN[1],b[i],length(LN));     inc(i,Length(LN));
     PBYTE(@(b[i]))^ := 0;             inc(i,1);

     // NickName
     PWORD(@(b[i]))^ := length(NN)+1;  inc(i,2);
     MOVE(NN[1],b[i],length(NN));     inc(i,Length(NN));
     PBYTE(@(b[i]))^ := 0;             inc(i,1);

     // дозаполним "ненужную" длину в начале массива
     PWORD(@(b[0]))^ := i-2;
     // создаем FLAP-пакет
     P:=CreatePacket(2,SEQ);
     // добавляем SNAC(15,2)
     SNACAppend(p,$15,$2);
     // добавляем TLV(1) с данными из промежуточного массива
     TLVAppend(p,1,i,@b);
     // шлем запрос
     Form1.PacketSend(p);
     // пишем в Memo
     M(Form1.Memo,'> Search Detail: Nick:'+NN+
                               '   First:'+FN+
                                '   Last:'+LN+'   '+
                                 'Cookie:$'+inttohex(Cookie,4));
end;

Запросы других подтипов передаются аналогично. С небольшими вариациями. Оновременно можем передавать на сервер много запросов. Сервер разберется. Ведь в каждом нашем запросе есть уникальное(ый) Cookie (а также и RequestID в SNAC-заголовке). Сервер пометит свои пакеты-ответы этими же опознавательными знаками.

Я лично делаю проверку(сверку) только по Cookie. Выдавая запрос, запоминаю Cookie. А когда приходит ответ от сервера, то процедура-обработчик SNAC_15_3 просто использует WinAPI функцию PostMessage для передачи ответа окну, которое выдало запрос. В параметрах PostMessage указан Cookie из ответа сервера. Какое окно его опознает - значит тому окну и предназначен ответ.

Работа процедуры-обработчика SNAC_15_3 уже ранее рассматривалась. Сейчас она просто дополнена новыми блоками, обрабатывающими новые ответы сервера. Следует упомянуть, что на один (единственный) наш запрос сервер присылает сразу целый массив из SNAC-ответов. Это типичная ситуация.

Например: запрашиваем Инфо о клиенте SNAC(15,2) [подтип запроса B204].

В ответ получим сразу восемь SNAC-ответов.

Вот их краткие названия-описания:

  • main-home-info
  • homepage-more-info
  • more-email-info
  • additional-info
  • work-info
  • about
  • personal-interests
  • past-background

Все полученные данные теперь сохраняются в файле .dat






Copyright © 2004-2016 "Delphi Sources". Delphi World FAQ




Группа ВКонтакте   Ссылка на Twitter   Группа на Facebook