Конференция "Сети" » Проблема с компонентами TidTCPServer и TidTCPClient [D7, WinXP]
 
  • Сергей М. © (01.12.09 08:23) [20]

    > maxistent ©   (30.11.09 17:38) [15]


    Например, так:

    var
     ptrDataToRender: Pointer;
    ..
     ptrDataToRender := SysGetMem(dwBytesReadFromClient);
     try
       CopyMemory(ptrDataReadFromClient, ptrDataToRender, dwBytesReadFromClient);
       PostMessage(MyRenderForm.Handle, WM_DATA_TO_RENDER_AVAIL, Pointer(dwBytesReadFromClient), Self);
     except
        FreeMem(ptrDataToRender);
        raise;
     end;
  • maxistent © (01.12.09 09:15) [21]
    в общем, пробывал сделать по таймеру, пипец получается. в смысле, задержка большая. пробывал в отдельном потоке - тут одно из двух, либо ошибка (типа не успевает прорисовываться, JPEG Error #43,#52 и т.д.), либо, если поставить что-то вроде sleep(1/5/10) то опять-таки тормозит :( что делать даже не знаю..
  • maxistent © (01.12.09 09:27) [22]

    > Сергей М. ©   (01.12.09 08:23) [20]

    Не пойму как это применить? можно пояснить что к чему? например что есть ptrDataReadFromClient? указатель на TJPEGImage? и что за сообщение такое WM_DATA_TO_RENDER_AVAIL? что в этом блоке кода происходит, объясни если не сложно?
  • Сергей М. © (01.12.09 09:28) [23]
    > что делать даже не знаю

    Ему про фому, он всё про ерему)

    Ты в [14],[20] вник ?
  • maxistent © (01.12.09 09:31) [24]
    в [14] да, а вот в [20] не совсем. поэтому и прошу объяснить
  • maxistent © (01.12.09 09:45) [25]
    вопросы:
    1) WM_DATA_TO_RENDER_AVAIL - это, как я понимаю, МОЕ СОБСТВЕННОЕ сообщение, так? тогда как его обработать потом?
    2) в строке
    PostMessage(MyRenderForm.Handle, WM_DATA_TO_RENDER_AVAIL, Pointer(dwBytesReadFromClient), Self);

    вообще не пойму что происходит.. отправляем окну сообщение - это понятно, а что в параметрах?..
  • Сергей М. © (01.12.09 09:46) [26]

    > что есть ptrDataReadFromClient?


    Указатель на очередной блок данных, полученный сервером от клиента в теле OnExecute.


    > что за сообщение такое WM_DATA_TO_RENDER_AVAIL?


    Константа-идентификатор предопределенного тобой пользовательского сообщения, например, WM_USER + 1000


    > что в этом блоке кода происходит


    Очередной блок данных, который твой сервер получил в OnExecute от клиента и который должен быть отрисован формой в осн.потоке, копируется в подготовленный (выделением памяти) буфер, указатель на этот буфер передается параметром wParam асинхронного сообщения окну твоей формы.

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

    В OnExecute:

    var
    ptrDataToRender: Pointer;
    ..
    ptrDataToRender := SysGetMem(dwBytesReadFromClient);
    try
      CopyMemory(ptrDataReadFromClient, ptrDataToRender, dwBytesReadFromClient);
      PostMessage(MyRenderForm.Handle, WM_DATA_TO_RENDER_AVAIL, WPARAM(ptrDataToRender), LPARAM(dwBytesReadFromClient));
    except
       FreeMem(ptrDataToRender);
       raise;
    end;

    В юните формы:

    const
     WM_DATA_TO_RENDER_AVAIL = WM_USER + 1000;
    ..
    TMyForm = class(TForm)
    ...
    private
    ..
     procedure WMMyMessage(var Message: TMessage); message WM_DATA_TO_RENDER_AVAIL;
    ..
    end;
    ..
    procedure TMyForm.WMMyMessage(var Message: TMessage);
    var
     ptrDataToRender: Pointer;
     dwSizeOgDataToRender: DWord;
    begin
     ptrDataToRender := Pointer(Message.wParam); // вот тебе адрес буфера
     dwSizeOgDataToRender := DWord(Message.lParam); //вот тебе размер данных в этом буфере
     try
    .. тут обрабатывай его как угодно - хоть рисуй его где хочешь, хоть еще что-то ..
     finally
       FreeMem(ptrDataToRender); // и обязательно освободи память, выделенную в OnExecute под этот буфер !!
     end;
    end;
  • maxistent © (01.12.09 11:50) [27]
    теперь понятно, спасибо. только данные приходят "левые" какие-то :( может что-то с указателями не так?

    > ptrDataToRender := Pointer(Message.wParam); // вот тебе
    > адрес буфера

    вот тут явно не тот буфер (я проверял), который был изначально в OnExecute, хотя dwSizeOfDataToRende имеет правильное значение. что-то тут не так..
  • Сергей М. © (01.12.09 11:59) [28]

    > что-то тут не так


    Угу.
    Ошибка у тебя в программе, в 17-й строке)
  • maxistent © (01.12.09 12:20) [29]
    нет, врядли =) в 17-й строке написано
    TForm1 = class(TForm)


    ну а если серьезно? почему данные, полученные обработчиком сообщения (procedure WMMyMessage(var Message: TMessage)) отличаются от тех, которые были изначально ему переданы? отличается именно буфер!
  • Сергей М. © (01.12.09 12:24) [30]
    У тебя с головой и логикой вообще все в порядке ?)

    Ты где-то там накосячил, код ты показывать не желаешь, а я должен догадаться с 3-х раз, где и что у тебя там не так ?)
  • brother © (01.12.09 12:37) [31]
    ну, партизан... код показывай уже а? что за ё маё?
  • maxistent © (01.12.09 12:39) [32]
    ну вот такой у меня код:

    procedure TForm1.ss1Execute(AThread: TIdPeerThread);
    var
    buf:pointer;
    DataSize:integer;
    st:TStream;
    r0:TRect;
    p0:TPoint;
    ptrDataToRender:Pointer;
    begin
    AThread.Connection.ReadBuffer(p0,sizeof(p0));//"габариты" всей картинки
    AThread.Connection.ReadBuffer(r0,sizeof(r0));//позиция текущего фрагмента
    AThread.Connection.ReadBuffer(DataSize,sizeof(DataSize));//размер изображения (jpg)
    GetMem(buf,DataSize);
    AThread.Connection.ReadBuffer(buf^,DataSize);

    //тут я все это складываю в стрим...
    st:=TMemoryStream.Create;
    st.Write(p0,sizeof(p0));
    st.Write(r0,sizeof(r0));
    st.Write(buf^,DataSize);
    FreeMem(buf,DataSize);
    st.Position:=0;
    //потом читаю это все в память...
    DataSize:=st.Size;
    GetMem(buf,DataSize);
    st.Read(buf^,DataSize);
    st.Free;

    //и передаю дальше...
    ptrDataToRender := SysGetMem(DataSize);
    try
      CopyMemory(buf, ptrDataToRender, DataSize);
      PostMessage(Form1.Handle, WM_DATA_TO_RENDER_AVAIL, WPARAM(ptrDataToRender), LPARAM(DataSize)); except
      FreeMem(ptrDataToRender);
      raise;
    end;
    FreeMem(buf1,DataSize);
    end;

    procedure TForm1.WMMyMessage(var Message: TMessage);
    var
    ptrDataToRender: Pointer;
    dwSizeOfDataToRender: DWord;
    st:TStream;
    jpg:TJPEGImage;
    p:TPoint;
    r:TRect;
    begin
    ptrDataToRender := Pointer(Message.wParam);
    dwSizeOfDataToRender := DWord(Message.lParam);
    try
    //дальше я уже не могу ничего сделать - буфер не тот, но в переменной
    //dwSizeOfDataToRender значение верное
    { st:=TMemoryStream.Create;
    st.Write(ptrDataToRender^,dwSizeOfDataToRender);
    st.Position:=0;
    st.Read(p,sizeof(p));
    st.Read(r,sizeof(r));
    jpg:=TJPEGImage.Create;
    jpg.LoadFromStream(st);
    st.Free;
    Image1.Picture.Bitmap.Canvas.Draw(r.Left,r.Top,jpg);
    jpg.Free;}

    finally
      FreeMem(ptrDataToRender);
    end;
    end;

  • CrytoGen (01.12.09 12:45) [33]
    молодец
     FreeMem(ptrDataToRender);
  • Сергей М. © (01.12.09 12:53) [34]

    > CopyMemory(buf, ptrDataToRender, DataSize);


    Это что за ерунда ?!
    Да еще и с учетом [33] ?
  • maxistent © (01.12.09 12:55) [35]
    что? где? в чем моя ошибка? я понимаю (во всяком случае подозреваю), что с указателями что-то напутал, но где именно - не могу понять
  • Сергей М. © (01.12.09 12:59) [36]
    > в чем моя ошибка?

    Их минимум две:

    1. Собственноручно уничтожил только что принятые данные, см. [33]
    2. Поменял местами источник и приемник в операции копирования (CopyMemory), указав к тому же в кач-ве приемника адрес уже не существующего буфера, который ты см. п.1
  • maxistent © (01.12.09 13:06) [37]
    сорри, по поводу п.2 это я протупил. да, действительно перепутал. сейчас поменял местами - то же самое. в каком месте нужно выполнять
    FreeMem(ptrDataToRender);

    ?
  • CrytoGen (01.12.09 13:20) [38]
    вообще странный код:
    ptrDataToRender := SysGetMem(DataSize);
    try
     CopyMemory(buf, ptrDataToRender, DataSize);
     PostMessage(Form1.Handle, WM_DATA_TO_RENDER_AVAIL, WPARAM(ptrDataToRender), LPARAM(DataSize)); except
     FreeMem(ptrDataToRender);
     raise;
    end;
    FreeMem(buf1,DataSize);



    что за buf1?
    почему raise?

    FreeMem правильно написан
    finally
     FreeMem(ptrDataToRender);
    end;
  • Сергей М. © (01.12.09 13:33) [39]
    > в каком месте нужно выполнять FreeMem(ptrDataToRender);?

    Минимум в 2-х:

    1. на стороне отправителя - при исключении.
    2. На стороне получателя - безусловно.
 
Конференция "Сети" » Проблема с компонентами TidTCPServer и TidTCPClient [D7, WinXP]
Есть новые Нет новых   [134438   +31][b:0][p:0.002]