Конференция "Сети" » Проблема с компонентами TidTCPServer и TidTCPClient [D7, WinXP]
 
  • maxistent © (30.11.09 06:57) [0]
    Доброго времени суток. Подскажите как правильно использовать компоненты TidTCPServer и TidTCPClient для передачи данных? На сервере в OnExecute можно просто сделать что-то вроде AThread.Connection.ReadBuffer(Data,DataSize)? или надо как-то по-особому обрабатывать этот эвент? Собственно проблема вот в чем: пишу софт для передачи картинки с экрана в реалтайме (ну или почти в реалтайме). Получилось что-то вроде этого:

    с клиента передаю данные idTcpClient1.WriteBuffer(...);

    на сервере принимаю так:


    procedure TForm1.ss1Execute(AThread: TIdPeerThread);
    var
    buf1,buf2:pointer;
    DataSize:integer;
    st:TStream;
    jpg:TJPEGImage;
    r:TRect;
    begin
    AThread.Connection.ReadBuffer(DataSize,sizeof(DataSize));
    AThread.Connection.ReadBuffer(r,sizeof(r));
    GetMem(buf1,DataSize);
    AThread.Connection.ReadBuffer(buf1^,DataSize);
    st:=TMemoryStream.Create;
    st.Write(buf1^,DataSize);
    FreeMem(buf1,DataSize);
    st.Position:=0;
    jpg:=TJPEGImage.Create;
    jpg.LoadFromStream(st);
    st.Free;
    image1.Picture.Bitmap.Canvas.draw(r.Left,r.Top,jpg);
    jpg.Free;
    end;



    При подключении начинается передача изображения, но через несколько секунд (~5 сек) изображение перестает обновляться, а еще через несколько секунд прога "вылетает" с сообщением <Canvas does not allow drawing>. что здесь не так? не могу понять...
  • maxistent © (30.11.09 07:21) [1]
    Блин, протупил =)) решил проблему двумя дополнительными строчками кода:


    image1.Picture.Bitmap.Canvas.Lock;
    image1.Picture.Bitmap.Canvas.draw(r.Left,r.Top,jpg);
    image1.Picture.Bitmap.Canvas.UnLock;



    Вроде работает...

    Остался только вопрос по поводу правильности обработки эвента OnExecute - правильный он у меня или все-таки нет?
  • maxistent © (30.11.09 08:14) [2]
    Вообще не могу понять, как организовать двухстороннюю связь с помощью этих компонентов? На сервере нужно всем клиентам рассылать команды, а как это сделать - не знаю  :(  пробывал вызвать
    idTCPServer.bindings.items[i].Send(buf,x,0)


    но как тогда на клиентах принять эти данные - не пойму..
    пробывал на клиенте создать отдельный поток и в нем вызывать
    idTCPClient.ReadBuffer(buf,x)


    но данные туда не приходють :(
    что делать - не знаю.. нигде толком не объясняют как организовать непрерывную двухстороннюю связи сервера с несколькими клиентами.
    Помогите, хто чем может, плииииз!
  • brother © (30.11.09 08:39) [3]
    > На сервере нужно всем клиентам рассылать команды

    и

    > как организовать двухстороннюю связь

    О_о
    для клиента связь: клиент- сервер (сеанс),
    для сервера: сервер (сеансы) - много клиентов
    ?
  • CrytoGen (30.11.09 08:41) [4]
      l:=TCPTranslation.Threads.LockList;
      for i:=0 to l.Count-1 do
      begin
        TIdPeerThread(l.Items[i]).Connection.WriteBuffer(...);
    //     TIdPeerThread(l.Items[i]).Connection.Disconnect;
      end;
      TCPTranslation.Threads.UnlockList;



    а на клиенте необходимо создать поток и читать в нём.
  • brother © (30.11.09 08:43) [5]
    > На сервере нужно всем клиентам рассылать команды

    кстати, какие? тыж вроде хочешь слать картинки?
  • Сергей М. © (30.11.09 09:06) [6]

    > maxistent ©   (30.11.09 08:14) [2]



    > двухстороннюю связь


    Ерунду ты задумал.
    Либо клиент командует серверу и тот исполняет команды, либо наоборот.
  • maxistent © (30.11.09 09:32) [7]

    > CrytoGen [4]


    А что за TCPTranslation? это к чему относится?


    > brother ©   (30.11.09 08:43) [5]
    > > На сервере нужно всем клиентам рассылать команды
    > кстати, какие? тыж вроде хочешь слать картинки?


    я посылаю комманду, а за ней уже идут данные (например, изображение)


    > Сергей М. ©   (30.11.09 09:06) [6]
    > Ерунду ты задумал. Либо клиент командует серверу и тот исполняет команды, либо наоборот.


    Почему же ерунду? клиенты выполняют команды сервера, а сервер в свою очередь выполняет команды клиентов. поэтому мне и нужно реализовать двухсторонний обмен данными.
  • maxistent © (30.11.09 09:37) [8]
    ну на стороне клиентов проще - там просто в потоке я читаю вот так:
    idTCPClient.ReadBuffer(buf,x)

    и мне этого в принципе достаточно, а с отправкой вообще никаких проблем. А вот как на стороне сервера отправить всем или выборочным клиентам данные - не знаю. допустим, на сервере выполнили действие ОТПРАВИТЬ СООБЩЕНИЕ (образно), выбрали ВСЕХ или НЕСКОЛЬКИХ клиентов и он должен этим клиентам разослать это сообщение. вот как это сделать я не знаю. подскажите?
  • maxistent © (30.11.09 09:47) [9]

    > CrytoGen   (30.11.09 08:41) [4]

    сделал по твоему примеру, вроде работает. спасибо.
  • Сергей М. © (30.11.09 10:04) [10]

    > Почему же ерунду?


    Потому что.

    Читать сюда

    http://pda.delphimaster.net/?n=18&id=1251710046

    до полного просветления.

    В особенности пост [61] - это как раз твой печальный случай.

    И не надо ходить по лесу из граблей.
  • maxistent © (30.11.09 13:53) [11]
    вроде разобрался, но появилась такая проблема:
    я в потоке TIdPeerThread получаю изображение, потом пытаюсь его вывести на экран и "вылетает ошибка". я так понимаю мне нужно из этого потока как-то "временно выйти" (илипоставить на паузу), произвести отрисовку, и пото вернуться обратно? или я что-то не так понимаю? :(
  • Сергей М. © (30.11.09 14:32) [12]
    Рисование на канве VCL-контролов в доп.потоках недопустимо.
  • maxistent © (30.11.09 15:04) [13]
    и как быть?
  • Сергей М. © (30.11.09 15:10) [14]
    Известно как - извещать (любым удобным способом, синхронно или асинхронно - выбор за тобой) осн.поток о необходимости отрисовки там-то таких-то граф.данных.
  • maxistent © (30.11.09 17:38) [15]
    ну например как? допустим у меня на форме динамически создаются объекты TImage. в них нужно выводить в определенных местах небольшие графические фрагменты (что-то вроде
    Image1.picture.bitmap.canvas.draw(x,y,jpg)

    )
    но делать это надо после того, как будет получен от клиента очередной фрагмент, в событии OnExecute
  • CrytoGen (30.11.09 17:58) [16]
    например использовать Synchronize - что не очень удобно
    или сделать примерно так

    var
     GlobalImage    : TBitmap;
     newImageFlag : boolean;
    ...
    //получение данных
    GlobalImage.Assign(TCPImage);
    newImageFlag:=True;
    ...
    //таймер
    if newImageFlag then
    begin
     Image1.Canvas.Draw(0,0,GlobalImage);
     newImageFlag:=False;
    end;
    ...


  • maxistent © (30.11.09 19:43) [17]
    блииин... тогда задержки большие будут :( а другие, более "гуманные" варианты (в плане быстродействия) существуют?
  • CrytoGen (30.11.09 20:20) [18]
    20 мс большая задержка?
  • brother © (01.12.09 05:00) [19]
    > 20 мс большая задержка?

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