-
Доброго времени суток. Подскажите как правильно использовать компоненты 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>. что здесь не так? не могу понять...
-
Блин, протупил =)) решил проблему двумя дополнительными строчками кода:
image1.Picture.Bitmap.Canvas.Lock;
image1.Picture.Bitmap.Canvas.draw(r.Left,r.Top,jpg);
image1.Picture.Bitmap.Canvas.UnLock;
Вроде работает... Остался только вопрос по поводу правильности обработки эвента OnExecute - правильный он у меня или все-таки нет?
-
Вообще не могу понять, как организовать двухстороннюю связь с помощью этих компонентов? На сервере нужно всем клиентам рассылать команды, а как это сделать - не знаю :( пробывал вызвать idTCPServer.bindings.items[i].Send(buf,x,0) но как тогда на клиентах принять эти данные - не пойму.. пробывал на клиенте создать отдельный поток и в нем вызывать idTCPClient.ReadBuffer(buf,x) но данные туда не приходють :( что делать - не знаю.. нигде толком не объясняют как организовать непрерывную двухстороннюю связи сервера с несколькими клиентами. Помогите, хто чем может, плииииз!
-
> На сервере нужно всем клиентам рассылать команды
и
> как организовать двухстороннюю связь
О_о для клиента связь: клиент- сервер (сеанс), для сервера: сервер (сеансы) - много клиентов ?
-
l:=TCPTranslation.Threads.LockList;
for i:=0 to l.Count-1 do
begin
TIdPeerThread(l.Items[i]).Connection.WriteBuffer(...);
end;
TCPTranslation.Threads.UnlockList; а на клиенте необходимо создать поток и читать в нём.
-
> На сервере нужно всем клиентам рассылать команды
кстати, какие? тыж вроде хочешь слать картинки?
-
> maxistent © (30.11.09 08:14) [2]
> двухстороннюю связь
Ерунду ты задумал. Либо клиент командует серверу и тот исполняет команды, либо наоборот.
-
> CrytoGen [4]
А что за TCPTranslation? это к чему относится?
> brother © (30.11.09 08:43) [5] > > На сервере нужно всем клиентам рассылать команды > кстати, какие? тыж вроде хочешь слать картинки?
я посылаю комманду, а за ней уже идут данные (например, изображение)
> Сергей М. © (30.11.09 09:06) [6] > Ерунду ты задумал. Либо клиент командует серверу и тот исполняет команды, либо наоборот.
Почему же ерунду? клиенты выполняют команды сервера, а сервер в свою очередь выполняет команды клиентов. поэтому мне и нужно реализовать двухсторонний обмен данными.
-
ну на стороне клиентов проще - там просто в потоке я читаю вот так: idTCPClient.ReadBuffer(buf,x) и мне этого в принципе достаточно, а с отправкой вообще никаких проблем. А вот как на стороне сервера отправить всем или выборочным клиентам данные - не знаю. допустим, на сервере выполнили действие ОТПРАВИТЬ СООБЩЕНИЕ (образно), выбрали ВСЕХ или НЕСКОЛЬКИХ клиентов и он должен этим клиентам разослать это сообщение. вот как это сделать я не знаю. подскажите?
-
> CrytoGen (30.11.09 08:41) [4]
сделал по твоему примеру, вроде работает. спасибо.
-
-
вроде разобрался, но появилась такая проблема: я в потоке TIdPeerThread получаю изображение, потом пытаюсь его вывести на экран и "вылетает ошибка". я так понимаю мне нужно из этого потока как-то "временно выйти" (илипоставить на паузу), произвести отрисовку, и пото вернуться обратно? или я что-то не так понимаю? :(
-
Рисование на канве VCL-контролов в доп.потоках недопустимо.
-
и как быть?
-
Известно как - извещать (любым удобным способом, синхронно или асинхронно - выбор за тобой) осн.поток о необходимости отрисовки там-то таких-то граф.данных.
-
ну например как? допустим у меня на форме динамически создаются объекты TImage. в них нужно выводить в определенных местах небольшие графические фрагменты (что-то вроде Image1.picture.bitmap.canvas.draw(x,y,jpg) ) но делать это надо после того, как будет получен от клиента очередной фрагмент, в событии OnExecute
-
например использовать Synchronize - что не очень удобно или сделать примерно так
var
GlobalImage : TBitmap;
newImageFlag : boolean;
...
GlobalImage.Assign(TCPImage);
newImageFlag:=True;
...
if newImageFlag then
begin
Image1.Canvas.Draw(0,0,GlobalImage);
newImageFlag:=False;
end;
...
-
блииин... тогда задержки большие будут :( а другие, более "гуманные" варианты (в плане быстродействия) существуют?
-
20 мс большая задержка?
-
> 20 мс большая задержка?
а откуда такая точность?
|