Конференция "Сети" » Прием большого потока данных по UDP
 
  • MBo © (31.01.08 07:26) [0]
    Задача следующая - некий спецдевайс передает по сети по протоколу UDP данные (видеопоток), порядка 11 мегабайт в секунду, пакет 770 байт - строка. Прием занимает очень значительную часть процессорного времени (применяется WSA-функции + RecvFrom, также пробовал использовать Indy и ICS), причем, если программа занимается еще чем-то, то пакеты, приходящие  в этот момент, теряются. Например, если после приема кадра отрисовывать его, то несколько первых строк следующего кадра не принимаются.

    Можно ли предпринять какие-то меры к улучшению ситуации?
    C сетями ранее не работал, так что могут помочь любые идеи.
  • ketmar © (31.01.08 08:53) [1]
    собирать на отдельном сервере.
    поднять приоритеты получалке.
    настучать в тыкву авторам передавалки.

    %-)
  • Сергей М. © (31.01.08 08:55) [2]

    > если программа занимается еще чем-то


    Сделай так чтобы она занималась только этим и ничем более
  • MBo © (31.01.08 09:11) [3]
    т.е., такое потребление ресурсов и потери пакетов -  это нормальная ситуация?
  • Anatoly Podgoretsky © (31.01.08 09:13) [4]
    > MBo  (31.01.2008 07:26:00)  [0]

    Для такого потока нужен уже 1 гигабит, 11 мегабайт в секунду можно передать только в тепличных условиях.
  • ketmar © (31.01.08 09:26) [5]
    >[3] MBo ©(31.01.08 09:11)
    для UDP — да. оно ж лежит в буфере только пока новое не притащат. да и не факт, что старое дойдёт. потеряется по дороге — и всё.
  • MBo © (31.01.08 09:43) [6]
    >11 мегабайт в секунду можно передать только в тепличных условиях
    судя по снифферу, в стомегабитной локалке до машины пакеты доходят все, да и если программа не занимается обсчетом/отрисовкой, то она их все принимает.

    >оно ж лежит в буфере
    насчет размера буфера я пока не разобрался. В ICS и в Indy можно выставить размер буфера, который, как я понимаю, отвечает за максимальный размер пакета. А есть ли еще какие-то возможности указать сетевой подсистеме винды, чтобы побольше непрочитанных еще пакетов накапливалось?
  • ketmar © (31.01.08 09:48) [7]
    >[6] MBo ©(31.01.08 09:43)
    а максимальный размер пакета, афаир, всё равно 64к. и очереди в UDP нет. не успал поймать — кранты тому, что лежало.
  • Сергей М. © (31.01.08 09:51) [8]

    > MBo ©   (31.01.08 09:43) [6]


    см. SetSockOpt(..SO_RCVBUF..)

    Но это не спасет, если выборка из буфера стабильно медленней, чем запись в буфер.
  • Anatoly Podgoretsky © (31.01.08 09:52) [9]
    > MBo  (31.01.2008 09:43:06)  [6]

    судя по снифферу, в стомегабитной локалке до машины пакеты доходят все, да и если программа не занимается обсчетом/отрисовкой, то она их все принимает.

    Этого не должно быть, что то неправильно, в программе конечно.
    Но я бы все таки задумался 11 мегабайт это на пределе возможностей 100 мб сети. Не каждая машина и сетевая карта в состоянии обеспечить.
    А для процессора это ничто, доли процента.

    Но сам протокол UDP не обеспечивает гарантированой доставки. Размер пакета надо снижать до минимума и делать буферизации, часть буферизации делает система.
  • Сергей М. © (31.01.08 09:53) [10]

    > MBo ©


    Выноси транспортную логику в отдельный поток, повысь ему приоритет до разумных пределов.
  • ketmar © (31.01.08 09:58) [11]
    >[10] Сергей М. ©(31.01.08 09:53)
    так нечестно, я это уже посоветовал! %-)
  • MBo © (31.01.08 10:11) [12]
    да, прием ведется в отдельном потоке, повышение приоритета частично помогает, но полностью проблему не снимает.
  • ketmar © (31.01.08 10:19) [13]
    >[12] MBo ©(31.01.08 10:11)
    ну, ты учти, что поток не может быть особо приоритетней приложения. подними ещё приоритет самому приложению. другим потокам приоритет поспускай.

    а лучше таки накапливай где-то на отдельном сервере и с него уже забирай. и на гигабитке, желательно.
  • MBo © (31.01.08 10:37) [14]
    > лучше таки накапливай где-то на отдельном сервере и с него уже забирай. и на гигабитке, желательно

    Увы, не получится - в реальности будут полевые условия, железка - кабель - ноутбук.
  • Сергей М. © (31.01.08 10:54) [15]

    > MBo ©   (31.01.08 10:37) [14]


    Ты бы код своего транспортного алгоритма показал ..
  • ketmar © (31.01.08 11:23) [16]
    >[15] Сергей М. ©(31.01.08 10:54)
    я подозреваю, что ничего там такого нет. тупо сетка успевает впритык.

    однако ж глянуть не помешает в любом случае, да.
  • MBo © (31.01.08 13:52) [17]

    инициализация в конструкторе потока

     if WSAStartup($0202, WSAD) <> 0 then
       Exception.Create('WSAStartup Error');
     Ud := Socket(AF_INET, Sock_Dgram, 0);
     if INVALID_SOCKET  = Ud then
       Exception.Create('Socket Create Error');
     Addr.sin_family := PF_Inet;
     Addr.sin_addr.S_addr := Inet_Addr('0.0.0.0');
     Addr.sin_port := HtoNS(FPort);
     FillChar(Addr.sin_zero, SizeOf(Addr.sin_zero), 0);
     if Bind(UD, Addr, SizeOf(Addr)) = Socket_Error then
       Exception.Create('Socket Bind Error');

    поточная функция

     Len := 770;
     while not Terminated do begin
       FromLen := SizeOf(TSockAddr);
       WSResult := RecvFrom(UD, LineBuf, Len, 0, Addr, FromLen);
       Wrd := Swap(PWord(@LineBuf[0])^);
       LineNum := Wrd and $3FF;
       CadrNum := (Wrd shr 12) and 1;

       if LineNum = 0 then begin
         Inc(FrameCount);
         PostMessage(Form3.Handle, WM_USER, FrameCount and $F, CadrNum xor 1);
       end;

       Move(LineBuf[2], Buf[CadrNum, LineNum, 0], Wdt);
     end;

    Buf - 2 массива, один заполняется, предыдущий отрисовывается

    в обработчике WM_USER отрисовка
     SetDiBitsToDevice(Canvas.Handle, 0, 0, Wdt, Hgt, 0, 0, 0, Hgt,
       @Buf[M.LParam], PBitmapInfo(@Info)^, DIB_RGB_COLORS);


  • ketmar © (31.01.08 14:11) [18]
    у-у-у. PostMessage… да ещё и SetDiBits… есть (ничем не обоснованое, правда) мнение, что:
    эту фигню надо тихонько совать в буфер моска сразу по получении. раз.
    наладить frame skiping, если не успевает отрисоваться, а в буферг гадит.
    рисовать директиксом на оверлеях (тут, возможно, вылезут тормоза с преобразованием цветовых пространств, искать карты, оверлеи на которых потянут rgb).

    да, это: присылает, как я понял, не твоя программа, так что вправить моск именно ей никак?
  • MBo © (31.01.08 14:32) [19]
    >PostMessage… да ещё и SetDiBits
    Отрисовку, временно забыв об опасностях обращения к основному окну из доп. потока, можно вести и прямо из потока, ничего принципиально это не меняет.
    SetDiBitsToDevice  - оказался в данном случае наименее затратный способ из испытанных (альтернатива, например - формирование битмапа, происходит дольше)

    насчет DirectX - еще не прорабатывал, побоялся затрат времени на преобразование цветов.
 
Конференция "Сети" » Прием большого потока данных по UDP
Есть новые Нет новых   [134431   +14][b:0][p:0.002]