Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.01.14;
Скачать: CL | DM;

Вниз

TWSocket разбор принятых пакетов   Найти похожие ветки 

 
цыц   (2006-08-16 17:53) [0]

Есть некий протокол, header которого оформлен таким образом:

BByte, BSize, BNum, BCrc


CByte (Byte) - это начало пакета, неизменяемая константа.
PSize (Word) - размер всего пакета, не считая размера заголовка
BNum (Word) - номер пакета, инкрементируется
BCrc (DWord) - контрольная сумма начинки

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

Всё это дело осуществляется с помощью TWSocket (www.overbyte.be)


type
  PHostHdr = ^THostHdr;
  THostHdr = record
    CByte: Byte;
    PSize: Word;
    BNum: Word;
    BCrc: DWord;
  end;

procedure WSocketOnDataAvailable(Sender: TObject; ErrCode: Word);
var
  recvHeader: PHostHdr;
  Count: integer;
begin
  if Error <> 0 then begin
     ShowMessage("Winsock error: " + IntToStr(Error));
     Exit;
  end;
 Count := WSocket2.Receive(@recvHeader, 9);
 if Count <= 0 then
   Exit;
....
....

 HLevelHandler(Наша начинка); // всё - обрабатываем в другой функции саму начинку.

end;


Вообщем, как это не глупо, но дальше я заглох. Я просто не знаю, что делать.
Считать заголовок, потом узнав из заголовка длину, сичтать весь пакет, но если пакет весь не успел дойти?
Вообщем нужен какой-то буфер, в который будут складываться пакеты. Нужно, что бы корректно всё обрабатывалось. Но я уже закипел просто.

Помогите пожалуйста, желательно с кодом.


 
Ketmar ©   (2006-08-16 21:58) [1]

код сам -- это полезно. тем более, что словами уже описано. заводишь флажок состояния (который показывает, что "в процессе": заголовок или данные). собираешь в буфер по получению. проверяешь, не пришёл ли полный пакет. если пришёл, разбираешь. всё.


 
Ketmar ©   (2006-08-16 21:58) [2]

тьфу. не надо никакого флажка. достаточно "убирать" разобраные пакеты из буфера. %-)


 
цыц   (2006-08-17 16:39) [3]

Спасибо за совет, но я так и застрял на фазе воплощения этого совета в корректный код. Может ещё, чем поможете. Я пытался конструировать мысли так.

Я уже запутался, ну например заводим буфер. Заведомо больший, для ситуации если примется сразу несколько пакетов.
Затем мы забираем всё пришедшее из сокета в наш буфер.
Проверяем длину принятого, если <= 0, то выходим.
Читаем из буфера, наш заголовок.
Из заголовка читаем длину начинки пакета.
Проверяем условием Длина_заголовка_Начинки >= Длина_принятого_пакта - Длина_заголовка

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

type
 PHostHdr = ^THostHdr;
 THostHdr = record
   CByte: Byte;
   PSize: Word;
   BNum: Word;
   BCrc: DWord;
 end;

procedure WSocketOnDataAvailable(Sender: TObject; ErrCode: Word);
const
 HEADER_LENGTH = 9;
var
 recvHeader: PHostHdr;
  Count: integer;
  WSockBuffer: array [0..$ffff] of Byte;
begin
 if Error <> 0 then begin
   ShowMessage("Winsock error: " + IntToStr(Error));
   Exit;
 end;

 Count := WSocket2.Receive(@WSockBuffer, SizeOf(WSockBuffer));
 if Count <= 0 then
   Exit;

 WSockBuffer[Count] := $00;
 recvHeader := @WSockBuffer[0];
 if recvHeader^.DataLen >= Count - HEADER_LENGTH then
 ..............  
end;


 
Ketmar ©   (2006-08-17 16:53) [4]

> [3] цыц   (17.08.06 16:39)
> Дальше не знаю
ну дальше же очевидно. а у Вас баги. %-)
буфер не должен быть локальной переменной -- весь смысл буфера в том, чтобы хранить данные между вызовами OnDataAvailable(). равно как и счётчик заполненности буфера, кстати.

далее: когда пришёл весь пакет, забираем его из буфера. сдвигаем остаток буфера в начало (это Move() %-), исправляем count. и так далее.

зыж кстати, можно не делать огромный буфер, а просто не читать больше одного пакета. %-)


 
Сергей М. ©   (2006-08-17 17:03) [5]


> Затем мы забираем всё пришедшее из сокета в наш буфер


А нахрена забирать все пришедшее ?

Забирай ровно столько, сколько осталось для заполнения текущей принимаемой структуры.

А то что не забрал - не пропадет, уверяю тебя)... Только не спрашивай почему - на то есть, цумбайшпиль, book.itep.ru


 
цыц   (2006-08-17 17:10) [6]


> зыж кстати, можно не делать огромный буфер, а просто не
> читать больше одного пакета. %-)


А можно чуть подробнее.

Я лучше всю схему понял при использовании флага: считываем из сокета длину заголовка, устанавливам флаг. Т.к. не все данные из сокета забрали (или они ещё не пришли), срабатывает во второй раз OnDataAvailable, и вот тут мы и считываем всю начинку из пакета по длине из заголовка и возвращаем флаг в обратное положение. И Дальше история повторяется с начала. Но хочется обойтись без заведения флага состояния.


 
Ketmar ©   (2006-08-17 17:16) [7]

> [6] цыц   (17.08.06 17:10)
во-первых: никто тебе не гарантирует, что во второй раз ты прочитаешь ВСЁ. равно как и не гарантирует получение сразу всего заголовка. для этого и нужен буфер. теоретически возможна ситуация, когда пакет будет приодить по одному байту, например. ы?

а флагом у тебя уже работает счётчик заполненности буфера. по-совсместительству. %-)


 
цыц   (2006-08-17 17:34) [8]


> [7] Ketmar   (17.08.06 17:16) 


Ну вообщем я понял прелести буфера, но опять не понимаю некоторых вещей. Как мне уже выше посоветовали, считывать только заголовок, не делать огромный буфер.

OnDataAvailable: Забираю из сокета только заголовок если вдруг и он будет идти по частям? Как предусмотреть все ситуации и предусмотреть все возможные проблемы. Я запутался.


 
DiamondShark ©   (2006-08-17 17:40) [9]


> если вдруг и он будет идти по частям?

забирать по 1 байту. меньше частей не бывает.
а как заголовок собрали, забирать тело.



Страницы: 1 вся ветка

Текущий архив: 2007.01.14;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.028 c
2-1167114999
Константин_
2006-12-26 09:36
2007.01.14
Оптимизация при открытии окна


2-1166641119
Signate
2006-12-20 21:58
2007.01.14
Манипуляции с TSocket...


4-1156987026
supervk
2006-08-31 05:17
2007.01.14
разделение общего ресурса на несколько потоков


6-1155393386
mr. Eof
2006-08-12 18:36
2007.01.14
Удаленное чтение файла


1-1164337278
UserControl
2006-11-24 06:01
2007.01.14
Список фреймов / панелей