Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

ICQ2000 сделай сам 3

Delphi , Интернет и Сети , ICQ

ICQ2000 сделай сам 3


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

Разговор по аське:
- Что замолчал?
- Пальцы устали.

Итак, рассмотрим механизм приема FLAP-пакетов. Прием пакетов - это обработчик события onReadData нашего ClientSocket. Задача этого обработчика сводится только к приему FLAP-пакетов и формировании из них связного списка типа FIFO (первым пришел, первым и ушел). Главное корректно отработать границы пакетов.

Каждый пакет принимается в два захода:

  1. сначала принимаем только заголовок FLAP-пакета (всего 6 байт);
  2. затем, узнав из заголовка длину блока данных, принимаем последний (ни байтом больше, ни байтом меньше).

Приняв полный пакет, формируем из него элемент списка FIFO и присоединяем его к списку. Смотрим, как это сделано у меня. Для прима заголовка и блока данных FLAP-пакета объявлены два массива: FLAP и FLAP_DATA соответственно.


procedure TForm1.CLI_ReadData(Sender:TObject; Socket:TCustomWinSocket);
var num,Bytes,fact : integer;
    pFIFO,CurrFIFO : PFLAP_Item;
    buf : array[0..100] of byte;
begin
// узнаем, сколько всего данных уже есть в буфере ClientSocketa
     num := Socket.ReceiveLength;
// в icq_Login мы установили isHdr, т.к. сначала ожидаем заголовок
     if isHDR then begin
// если есть как минимум 6 байт, то читаем 6 байт заголовка в FLAP
       if num>=6 then begin
         Socket.ReceiveBuf(FLAP,6);
// из заголовка узнаем длину блока данных FLAP-пакета
         NeedBytes := swap(FLAP.Len);
// сбрасываем в начало индекс массива FLAP_DATA
         index := 0;
// сбпасываем, чтобы следующее чтение было в FLAP_DATA
// и выходим из обработчика
       isHDR := false;
       end else begin
             // вообще-то ситуация, когда в Sockete меньше 6-и байт
             // пока никак не контролируется (возникает очень редко :)
             // отмечаю этот факт только в окне отладки 
             M(Memo,'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!');
             Socket.ReceiveBuf(buf,num);
             M(Memo,Dim2Hex(@(buf),num));
             M(Memo,'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!');
           end;

// if not isHDR then чтение в FLAP_DATA
end else begin  
// сколько байт читать уже известно: NeedBytes
         Bytes := NeedBytes;
// читаем их в FLAP_DATA[Index]
         fact := Socket.ReceiveBuf(FLAP_DATA[index],Bytes);
// если в Sockete было данных меньше чем нужно, 
// педвинем Index и NeedBytes для следующего входа в обработчик
         inc(index,fact);
         dec(NeedBytes,fact);
         if NeedBytes = 0 then begin
// если весь блок данных FLAP-пакета уже в FLAP_DATA,
// тогда выделаем память для элемента списка FIFO (PFLAP_Item) 
           New(pFIFO);
// копируем заголовок
           pFIFO^.FLAP := FLAP;
           pFIFO^.Next := nil;
// выделяем память для блока данных и копируем его
           GetMem(pFIFO^.DATA,index);
           move(FLAP_DATA,PFIFO^.Data^,swap(FLAP.Len));
           
// добавляем указатель на PFLAP_Item в список
           CurrFIFO:=HeadFIFO;
           if HeadFIFO<>nil then begin
             while CurrFIFO<>nil do
               if CurrFIFO^.Next=nil then begin
                 CurrFIFO^.Next:=pFIFO;
                 break;
               end else CurrFIFO:=CurrFIFO^.Next;
           end else HeadFIFO:=pFIFO; 
// устанавливаем isHDR (в true) уже для прима заголовка
// последующих FLAP-пакетов 
           isHDR := true; 
         end;
     end;
end;

Дальнейшая обработка списка FIFO - это задача уже другой процедуры.

Программный код - часть ICQ2000, популярного клиента мгновенного обмена сообщениями в конце 1990-х и начале 2000-х годов. Он написан на языке Pascal и использует среду разработки Delphi.

Код отвечает за обработку пакетов FLAP (Fast Lightweight Application Protocol), полученных от сервера через асинхронный сокет. Пакет FLAP состоит из заголовка и блока данных, которые разделены полем длины в заголовке.

Вот шаг за шагом, что код делает:

  1. Процедура CLI_ReadData вызывается, когда доступна новая информация для чтения из сокета.
  2. Сначала проверяется, есть ли достаточно данных в буфере (6 байт или более) для чтения заголовка FLAP. Если нет, то читаются доступные данные и хранятся в временном буфере.
  3. Если есть достаточное количество данных для чтения заголовка, извлекается длина блока данных из заголовка и сбрасывается переменная индекса index до 0.
  4. Затем цикл, где повторно читаются блоки данных из сокета, пока не будет получен целый пакет.
  5. Для каждого блока данных проверяется, есть ли достаточное количество данных в буфере для чтения всего блока. Если нет, то корректируются переменные индекса и длины для следующей итерации.
  6. Когда получен целый пакет, создается новый элемент в связанном списке (FIFO) для хранения данных пакета. Элемент содержит указатели на заголовок FLAP и блок данных.
  7. Затем обновляется флаг isHDR для указания, что следующий пакет будет иметь заголовок.

Код кажется выполняющим свою работу правильно, но есть некоторые минорные проблемы:

  • В случае, когда нет достаточного количества данных для чтения полного заголовка (6 байт или более), код не обрабатывает это состояние корректно. Он должен либо ждать прибытия дополнительных данных, либо игнорировать неполный пакет.
  • Код использует временный буфер buf для хранения частичных пакетов, но не ясно, почему это необходимо. Если сокет не может предоставить полный заголовок в одном проходе, может быть лучше использовать отдельный буфер для каждого пакета.

В целом, код выглядит как если бы он был написан с учетом производительности и эффективности, но некоторые минорные проблемы могут быть улучшены.

Автор статьи Александр Вага в этой статье рассматривает механизм приема FLAP-пакетов в приложении ICQ2k и описывает шаги для корректного формирования связного списка тип FIFO.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: ICQ ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-06-16 01:03:47/0.0058741569519043/1