Главная страница
    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.47 MB
Время: 0.012 c
2-1166701524
Vovan #2
2006-12-21 14:45
2007.01.14
Вместо локальной функции как параметра


15-1167043284
Post_
2006-12-25 13:41
2007.01.14
PostMessage


6-1155559604
Shaman_
2006-08-14 16:46
2007.01.14
idHTTP вылетает на HTTP/1.1 500 Internal Server Error


1-1164199903
Provodnick
2006-11-22 15:51
2007.01.14
Добавление Object в TRichEdit.Lines


11-1143547021
В13
2006-03-28 15:57
2007.01.14
JpegObj - kol ?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский