Автор: Alexander
Vaga WEB-сайт: http://icq2000cc.hobi.ru
Урок №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 |