Конференция "Сети" » ReceiveBuf. не могу разобраться как приавильно принять данные [D7, WinXP]
 
  • molinero (03.06.11 07:46) [20]
    FireMan_Alexey ©   (02.06.11 01:32) [19]

    Да какие обиды? Пинок в нужном направлении самое то!
  • FireMan_Alexey © (03.06.11 12:20) [21]
    В принципе принятие и отправку данных можно расписать по следующему алгоритму(во всяком случае я так делал):

    1. Создаешь буферы на прием и отправку!!!
    2. Ждешь события OnWrite потом посылаешь данные до тех пор, пока не получишь SOCKET_ERROR или данные не закончатся!!!
    3. Ждешь событие OnRead и складываешь все в буфер приема, а когда необходимое кол-во данных оказывается в буфере, то проверяешь на корректность и т.д.
    4. При дисконнекте освобождаешь буферы.
    5. ВСЕ!!! :)

    Сейчас поищу пример, только с моим компонентом! Но там должно быть понятно и так...
  • FireMan_Alexey © (03.06.11 13:17) [22]
    Type
     BuffType=Array of Byte;

    procedure TForm1.ClientSocket1Read(Sender: TObject;
     Socket: TCustomWinSocket);

    Var
     BuffTemp:BuffType;
     Size,ReadSize:Integer;
    begin
     Size:=Socket.ReceiveLength;
     SetLength(BuffTemp,Size);
     ReadSize:=Socket.ReceiveBuf(BuffTemp,Size);
     If ReadSize>0 Then BuffRead.Write(BuffTemp,ReadSize);
     SetLength(BuffTemp,0);
     {BuffRead - ìîé êëàññ, íî ìîæíî èñïîëüçîâàòü è TMemoryStream, íî ìîé óäîáíåé ;) }
     {!!!!!!!!Здесь обрабатываешь принятые данные!!!!!!!!!}
    end;

    Const
     MaxWrite=4096;

    procedure TForm1.ClientSocket1Write(Sender: TObject;
     Socket: TCustomWinSocket);
    Var
     BuffTemp:BuffType;
     Size,WriteSize:Integer;
    begin
     While BuffWrite.Size>0 do
       Begin
         SetLength(BuffTemp,MaxWrite);
         Size:=BuffWrite.Read(BuffTemp,MaxWrite);
         WriteSize:=Socket.SendBuf(BuffTemp,Size);
         SetLength(BuffTemp,0);
         If WriteSize>0 Then
           Begin
             BuffWrite.Position:=0;
             BuffWrite.Delete(WriteSize);
           End
         Else
           Break;
       End;
    end;



    Напиши, если нужен исходный код моего класса по типу MemoryStream!
    Он на дин, массивах! :)
  • FireMan_Alexey © (03.06.11 13:22) [23]
    Это то что иероглифами!!!

    {BuffRead - мой класс, но можно использовать и TMemoryStream, но мой удобней ;) }
  • Volkodav SR © (11.01.12 12:17) [24]
    Здравствуйте!
    Тоже бьюсь с сокетами, транспорт впринципе работает, но есть проблеммы.
    Подскажите пож-та кто знает. Проблема такая:
    В событиях по приему данных (ClinetRead или ServerClientRead) идет определение размера пакета данных и следом прием в цикле, пока весь пакет не будет принят. При этом находясь в режиме приема, это событие возникает несколько раз. Если процесс приема уже ведется и еще не закончен, то я выхожу из всех последующих срабатываний ClinetRead ....
    После приема пакета данных выхожу из события ...
    Проблема в том что при поступлении новых данных, событие ClinetRead или ServerClientRead в какой то произвольный момент может не сработать, несмотря на то что в сокете есть данные, оно перестает срабатывать. Если при этом принять данные в какой либо функции - событие продолжает работать.

    Можно ли какой либо командой выйдя из обработчика ClinetRead заставить сработать этот обработчик снова, если в сокете есть данные?
  • Сергей М. © (11.01.12 13:41) [25]
    На то есть три метода - ReceiveLength, ReceiveBuf и ReceiveText.

    Любому из этих методов методу глубоко фиолетово откуда их вызывают - из обработчика OnXXXRead
    или не из обработчика, на их работоспособность это никак не влияет.
  • Volkodav SR © (11.01.12 14:08) [26]

    > Сергей М. ©   (11.01.12 13:41) [25]

    Я использую методы ReceiveLength и ReceiveBuf.
    Смысл в том, что я не выхожу из обработчика OnXXXRead пока не будет принят весь известный мне оъбем данных. При этом событие OnXXXRead срабатывает неоднократно, а потом перестает срабатывать вообще. Прога при этом не висит.

    Ну то есть примерно так:
    1.Например сервер послал клиенту 100кб
    2.на клиенте возникает событие OnXXXRead
      так как не все 100 кб придут клиенту сразу событие OnXXXRead срабатывает у меня несколько раз ... но я принимаю данные (все 100кб) в первом событии, пока не приму все 100кб, а из последующих срабатываний событий выхожу ... после этого покидаю первое событие OnXXXRead, в котором принимал данные .... все хорошо ... работает, принимает, данные не теряет ....
    Когда сервер еще что нибудь пошлет, опять событие срабатывает, принимает ... НО НЕ ВСЕГДА, в какой то момент что то втыкается ...и не смотря на то что на клиент отосланы данные, событие OnXXXRead не срабатывает.

    Что то можно сделать вне обработчика OnXXXRead чтоб он опять сработал если в сокете есть данные?
    Или обязательно менять структуру приема данных?
  • Сергей М. © (11.01.12 15:09) [27]
    > я принимаю данные (все 100кб) в первом событии

    В режиме nonBlocking это неразумное решение.

    Возникло OnRead - обрабатывай его и читай в обработчике не более чем столько сколько в этот момент кажет ReceiveLength. Остальные данные никуда не пропадут - возникнут очередные OnRead и в них ты продолжишь получение очередных принятых от партнера и доступных данных.
  • Volkodav SR © (11.01.12 15:14) [28]
    Замечено, что при срабатывании события OnXXXRead, если не принять данные и выйти из него, то последующих срабатываний события OnXXXRead возникать не будет ...

    Так вот, можно ли сделать что нибудь ("переинициализировать" что ли ), чтоб при такой ситуации, оно сработало?
  • Сергей М. © (11.01.12 15:18) [29]

    > при срабатывании события OnXXXRead, если не принять данные
    > и выйти из него, то последующих срабатываний события OnXXXRead
    > возникать не будет


    Да, не будет, если из очереди поступивших от партнера данных тобой выбраны ВСЕ данные. Если же выбраны не все, то событие обязано возникнуть минимум еще однократно. И если оно у тебя не возникает, значит ты что-то накосячил в коде.
  • Volkodav SR © (11.01.12 15:19) [30]

    > Сергей М. ©   (11.01.12 15:09) [27]

    Ясно ...
    да, у меня nonBlocking ....

    ну тогда, мне предется переделывать схему приема и обработки данных ...
    типа писать все в TFileStream в OnRead, а в другом потоке производить разбор данных ... пойдет по такой схеме?
    только сложности на серверной стороне ... там ведь много клиеннтов может быть, разбор данных усложняется ...
  • Сергей М. © (11.01.12 15:26) [31]

    > мне предется переделывать схему приема и обработки данных


    А это уже твоя личная драма что ты сразу не пошел по верному пути.


    > писать все в TFileStream в OnRead, а в другом потоке производить
    > разбор данных ... пойдет по такой схеме?


    Такая схема еще дерьмовей.
    TFileStream тут как корове седло : наверняка вполне сойдет и TMemoryStream.
    Да и зачем другой поток, если ты даже при текущем решении без него обходишься ?
  • Volkodav SR © (11.01.12 15:46) [32]

    > Сергей М. ©   (11.01.12 15:26) [31]

    Большое спасибо за совет и разъяснеия!

    Ну как мне кажется ... в OnRead читать данные, сохранять, и быстро выходить ...
    А обрабатывать и геагировать на принятые данные уже в другом месте, в потоке, дабы не грузить остальную часть приложения ...  а?

    А FileStream вмесо MemoryStream чтоб память не занимать ... может напрасно конечно? :)
  • Сергей М. © (11.01.12 16:00) [33]

    > в OnRead читать данные, сохранять, и быстро выходить


    Именно так и правильно - на то и существует неблокирующий режим.
  • Volkodav SR © (11.01.12 17:29) [34]

    > Сергей М. ©   (11.01.12 16:00) [33]

    ОК - Спасибо!

    А как считаешь, лучше так реализовывать, как сказано выше, в неблокирующем режиме, или попробовать с блокирующим разобраться?

    Работать в блокирующем режиме я не пробовал?
  • Сергей М. © (11.01.12 17:49) [35]
    Тут

    http://www.delphisources.ru/pages/faq/images-indy/indy-in-depth-06.html

    краткий ликбез.

    Полный оригинал статьи Анатолия Подгорецкого:
    http://www.podgoretsky.com/ftp/Docs/Delphi/Podgoretsky/IndyInDepth.pdf

    Попробуй для начала вникнуть самостоятельно.
  • Volkodav SR © (11.01.12 19:23) [36]
    Хорошо!
    Спасибо!
 
Конференция "Сети" » ReceiveBuf. не могу разобраться как приавильно принять данные [D7, WinXP]
Есть новые Нет новых   [134435   +13][b:0][p:0.002]