![]() |
BMP bzw. Stream Indy TCPServer an alle verbundenen Clients schicken
Hi,
hat jemand ein gutes Beispiel, wie ich per Indy TCPServer ein Bitmap oder besser noch einen Stream an alle aktuell verbundenen Clients senden kann? Ich finde zwar viele Beispiele, wie ich das vom Client an den Server sende, aber ich habe bisher noch nicht viel in die andere Richtung gefunden. Der Client soll dabei nicht das letzte Bild abfragen, sondern solange er verbunden ist einfach unaufgefordert empfangen. Oder sollte ich das anders herum machen, dass der Client alle x Sekunden ein evtl. vorhandenes neues Bitmap abfragt? |
AW: BMP bzw. Stream Indy TCPServer an alle verbundenen Clients schicken
Ich melde mich als Interessent mit an :lol:
@Moderator: Kann man irgendwo aktivieren, dass man ein Thema mitlesen möchte? |
AW: BMP bzw. Stream Indy TCPServer an alle verbundenen Clients schicken
Wenn du E-Mail Benachrichtigungen an hast, wirst du automatisch informiert.
Zum eigentlichen Problem: der Server Socket hat sicher irgendwo eine Liste der verbundenen Clients. Da könnte man in einer Schleife die BMP Datei der Reihe nach an alle schicken. Das wäre aber bandbreitentechnisch ineffizient. Evtl. gibt es eine Multicast Möglichkeit? Alternativ UDP, da gehen im lokalen Netzwerk auch Broadcasts. |
AW: BMP bzw. Stream Indy TCPServer an alle verbundenen Clients schicken
Danke für die Antwort :thumb:
Zitat:
Zitat:
Und ich hatte schon mal den UDP-Server der Indies am Wickel. Entweder lag es an diesem, am UDP selbst oder an mir; jedenfalls wurden oft Pakete "verschluckt" (mir fällt keine andere Formulierung ein). |
AW: BMP bzw. Stream Indy TCPServer an alle verbundenen Clients schicken
Das Senden von IdTCPServer habe ich erst mal so gemacht:
Delphi-Quellcode:
Wo ich aber noch nicht weiß, wie ich das mit dem Datenempfang im IdTCPClient zu machen. Die Komponente besitzt ja keinen Trigger der mich über den Empfang benachrichtigt. Ich dachte mir ich packe das in einen Thread und frage laufend ab, ob Daten zum Empfang anliegen. Oder gibt es da eine bessere Möglichkeit?
procedure TForm2.OnScreenShot(Sender: TObject; BMP: Vcl.Graphics.TBitmap);
var i: Integer; List: TIdContextList; Context: TIdContext; ms: TMemoryStream; begin if idtcpsrvr1.Active then begin ms:=TMemoryStream.Create; try BMP.SaveToStream(ms); List:=idtcpsrvr1.Contexts.LockList; for I := 0 to List.Count-1 do begin Context:=TIdContext(List[i]); ms.Position:=0; Context.Connection.Socket.Write(ms, SizeOf(ms)); end; finally ms.Free; end; end; end; |
AW: BMP bzw. Stream Indy TCPServer an alle verbundenen Clients schicken
Hilft dir das vielleicht weiter:
![]() Im Endeffekt musst du dir mal ein Protokoll überlegen, wie Server und Client miteinander kommunizieren. Einfach nur die Bitmaps losschicken hilft ja nicht. Du müsstest etwas schicken das beinhaltet: "Achtung hier kommt ein Bitmap als Payload" "Bitmap/Payload ist beendet" "Jetzt kommt eine Prüfsumme/Hash" "Prüfsumme/Hash beendet" Jetzt kann der Client gucken, ob vom Payload alles angekommen ist und das ggf. nochmal anfordern. Hier vielleicht noch ein Tutorial dazu: ![]() |
AW: BMP bzw. Stream Indy TCPServer an alle verbundenen Clients schicken
Hallo,
der Client-Programm kann doch auch gleichzeitig Server sein. |
AW: BMP bzw. Stream Indy TCPServer an alle verbundenen Clients schicken
Muss es denn Indy sein? Nix dagegen, aber ICS (u.a. in GetIt) ist komplett event getrieben und asynchron.
Dein Client würde dort ein OnDataAvailable Event bekommen wenn die BMP reinkommt. |
AW: BMP bzw. Stream Indy TCPServer an alle verbundenen Clients schicken
Zitat:
![]() Der Client fragt halt in einem Extra-Thread im festgelegtem Abstand ab, ob es ein aktualisiertes Bild gibt, wenn ja, liefert der Server das direkt mit und der Thread aktualisiert dann die Anzeige (natürlich innerhalb eines Synchronize-Aufrufs). Auf dem Server innerhalb des Execute Events des Indy TCP Servers mache ich das dann einfach so (hier mal nur den Fall, dass der ganze Bildschirm übertragen werden soll, später übertrage ich nur sich zwischenzeitlich ergebene Änderungen):
Delphi-Quellcode:
Es wird also ein Stream erzeugt, das Bild geholt und in den Stream gespeichert. Dann wird zunächst die Größe des Streams (auch zur Kontrolle übermittelt) und dann der Stream selber gesendet.
{$Region 'Ganzen Bildschirminhalt übertragen'}
if pos ('getpic', sMsg) <> 0 then begin MyStream := TmemoryStream.Create; Try GetAPic (MyStream); MyStream.position := 0; SetKryptedStream (MyStream); // Image verschlüsseln, Stream steht danach bereits Position Zero AThread.Connection.IOHandler.WriteLn(myStream.Size.ToString); AThread.Connection.IOHandler.WriteBufferOpen; AThread.Connection.IOHandler.Write(myStream); AThread.Connection.IOHandler.WriteBufferClose; finally FreeAndNil(MyStream); end; EXIT; end; {$Endregion} |
AW: BMP bzw. Stream Indy TCPServer an alle verbundenen Clients schicken
Zitat:
- D.h. der Client muss also nicht ständig fragen "Server hast du mir Daten". Der Server sendet einfach... - Der Client muss keine Portweiterleitungen o.ä. im Router vornehmen. ![]() Kurz: Der Client verbindet mit dem Server. Du lässt die Verbindung Client-Server offen. Sobald Client oder Server Daten senden wollen tun sie das einfach... |
AW: BMP bzw. Stream Indy TCPServer an alle verbundenen Clients schicken
Zitat:
![]() ![]() ![]() Bis bald... Thomas |
AW: BMP bzw. Stream Indy TCPServer an alle verbundenen Clients schicken
Zitat:
|
AW: BMP bzw. Stream Indy TCPServer an alle verbundenen Clients schicken
Hallo Harry
meine Bemerkung zu tcp war genereller Art und nicht Indy/ICS oder was auch immer spezifisch. Ich verwende ausschliesslich ICS und kenne Indy sehr schlecht (und die 4'700 seitige PDF Anleitung mag nun echt niemand lesen ;-)). Aber soweit ich sehe, verwendet Indy "IOHandler" über welche die Kommunikation abgewickelt wird. Es gibt doch sicher Beispiele bei Emba. Wenn du dort keins findest ![]()
Delphi-Quellcode:
dann hast du ein "Client kann senden" und "Server darf aber auch" Beispiel.
procedure TFServer.SendeButtonClick(Sender: TObject);
begin broadcastmessage( SendeEdit.Text ); end; |
AW: BMP bzw. Stream Indy TCPServer an alle verbundenen Clients schicken
Zitat:
Das wird mir bei einer Reihe von meinen Netzwerkprogrammen das Handling sehr vereinfachen...:thumb: (Das ist ein schönes Beispiel hier, dass man auch mit Wissenszuwachs belohnt werden kann, wenn eigentlich selber weiterhelfen wollte...) Nachtrag: Interessanterweise scheint es dann so zu sein, dass mit der idTCPClient-Componente nach einem Writeln nicht mehr direkt eine Antwort des Servers abgefragt werden kann, da die idThreadComponente offensichtlich die Nachrichten zuerst abfängt. Meine bestehende Anwendung kann ich daher leider nicht so einfach umstellen (müsste Senden und Empfangen splitten), aber für neue Anwendungen sicher eine Option... |
AW: BMP bzw. Stream Indy TCPServer an alle verbundenen Clients schicken
Zitat:
Aber mal zum Thema zurück: Kümmern sich die Indys/ICS darum, dass die Pakete vollständig und in der richtigen Reihenfolge ankommen? Ein Screenshot - noch dazu als BitMap - dürfte recht groß sein. Wenn man das z.B. mittels VPN über das Internet sendet, wird das bei einer MTU von 1.500 Bytes sonst echt spannend. |
AW: BMP bzw. Stream Indy TCPServer an alle verbundenen Clients schicken
Um das Ankommen, die Reihenfolge und die Datenintegrität kümmert sich das Transport-Protokoll, also z.B. hier TCP/IP, nicht die Indy.
Die Packete sind nummeriert und werden bei Ankunft entsprechend behandelt. Indy kümmert sich nur um die Übertragungsprotokolle (HTTP/FTP/...). Bei UDP dagegen kann was verloren gehen, da nur "blind" gesendet wird, aber es keine Rückantwort gibt. |
AW: BMP bzw. Stream Indy TCPServer an alle verbundenen Clients schicken
Zitat:
D.h. du kannst zum Beispiel 5*32KB und dann noch 3*12KB senden - und alles kommt (bei tcp) immer in der korrekten Reihenfolge an. Ein Paket kann in mehreren Teilen ankommen, oder es landen gleich mehrere Pakete aufs Mal bei deinem Programm. Je nach verwendeter Methode zum Einlesen der Daten (Indy/ICS) merkst du davon was (oder eben auch nix). Wie weiter oben erwähnt wird: Wenn du über eine Verbindung zum Beispiel Chatmeldungen und Bitmaps senden willst, dann musst du für ein Protokoll sorgen, dank welchem du erkennst was ankommt. Am besten definierst du einen "Meldungstyp" in der Art: WAS WIEVIEL DATEN Wenn du eine Bitmap sendest, dann sendest du WAS=BITMAP WIEVIEL=LÄNGE DER DATEN DATEN=BITMAPDATEN. Wenn du eine Chatmeldung sendest, dann sendest du CHAT 5 HALLO. Der Empfänger liest ankommende Daten in einen Buffer, und übergibt diesen Buffer einem Parser, welcher checkt, ob eine vollständige Meldung angekommen ist. Wenn eine Meldung angekommen ist, dann löschst du die Meldung aus dem Buffer und rufst entsprechende Hilfsfunktionen (Chatmeldung anzeigen, Bitmap speichern etc.) auf. Wenn der Buffer noch nicht leer ist, dann rufst du erneut den Parser auf, bis sämtliche Befehle abgearbeitet sind. |
AW: BMP bzw. Stream Indy TCPServer an alle verbundenen Clients schicken
Ich stelle gerade fest, dass ich meine Frage wohl missverständlich formuliert habe. Entschuldigung!
Ich habe bereits ein Chat-Programm auf Basis der schon genannten Empfehlung, welches hier schon empfohlen wurde. Zitat:
Aber:
|
AW: BMP bzw. Stream Indy TCPServer an alle verbundenen Clients schicken
Zitat:
2. serverseitig: ja; clientseitig muss ein Thread verwendet werden wenn die restliche Anwendung nicht einfrieren soll |
AW: BMP bzw. Stream Indy TCPServer an alle verbundenen Clients schicken
[OT]
Zitat:
[/OT] |
AW: BMP bzw. Stream Indy TCPServer an alle verbundenen Clients schicken
Zitat:
|
AW: BMP bzw. Stream Indy TCPServer an alle verbundenen Clients schicken
Zitat:
Wenn du nur rasch "Hallo Server, gib mir was" senden willst, dann sind readln/writeln sicher ok - aber für komplexere Anwendungen bist du mit Indys IOHandler oder ICSOverbytes asynchronen Komponentan wesentlich flexibler unterwegs. |
AW: BMP bzw. Stream Indy TCPServer an alle verbundenen Clients schicken
Zitat:
|
AW: BMP bzw. Stream Indy TCPServer an alle verbundenen Clients schicken
Zitat:
|
AW: BMP bzw. Stream Indy TCPServer an alle verbundenen Clients schicken
Zitat:
Best practice ist daher, jeder Connection eine Queue zuzuordnen, in der über den Hauptthread Bilder hinzugefügt werden und die dann in OnExecute abgearbeitet wird. Die Clients werden dann parallel Daten erhalten, und die gesamte Steuerung der Kommunikation befindet sich in OnExecute. Wie man bei Indy weitere Attribute (wie z.B. eine Queue, oder Benutzernamen...) an die eingehenden Connections 'antackert' poste ich später. Es gibt einige Posts bei Stackoverflow in denen das beschrieben wird. |
AW: BMP bzw. Stream Indy TCPServer an alle verbundenen Clients schicken
Ich habe mittlerweile etwas lauffähiges zusammenbekommen.
Da ich mit Indey mittlerweise etwas besser kenne, bin ich dabei geblieben. ICS werde ich mir mal anschauen, aber da müsste ich mich neu einarbeiten. (Sind zwischen Indy und ICS performanceunterschiede bekannt? ) Ich habe das letztlich so gemacht, dass der Client halt beim Server sagt "Gib mir was" und der Server sendet halt per stream das Bild (zum verringern der Datenmenge als JPG) an den Client unmittelbar zurück. So weit, so gut. Vorerst habe ich damit das erreicht was ich wollte. Denn in meinem Fall reicht es aus in einem Interval von 10 Sekunden ein aktuelles Bild zu erhalten. Ich brauche keinen Livestream ala Teamviewer und ich muss auch nicht mit den anderen Bildschirm interagieren. Auch ist die interne Netzwerkstruktur hier nicht das Problem, denn ich habe selbst die Kontrolle über die Router/Firewalls dazwischen. Aber natürlich packt einen bei einem solchen Projekt auch ein wenig der Ergeiz. Mittlerweise habe ich mir die Display Duplication API angeschaut, mit deren Hilfe es natürlich einfacher ist, die Datenmenge zu veringern, weil man nach dem ersten Bild nur noch die Teilbilder schickt, in denen sich Änderungen ergeben. Damit läßt sich auch bei geringerer Bandbreit ein gutes Ergebnis erzielen. |
AW: BMP bzw. Stream Indy TCPServer an alle verbundenen Clients schicken
Zitat:
Habe daher eine neue Version veröffentlicht, bei Interesse ist ein kurzes Demo (ca. 1 Minute) bezüglich der Bildschirm-Übertragung hier zu sehen: ![]() Dabei muss ich anmerken, dass der Client in einer virtuellen Windows-Maschine lief und ich gleichzeitig das Video aufgenommen habe. "In echt" geht es also noch etwas schneller. Dabei hat sich heraus gestellt, dass die Indys gar nicht das Problem waren, sondern das Einfangen des aktuellen Bildschirms (auf dem älteren Entwicklungs-PC nicht unter 40 MS machbar, auf dem neuen müsste ich mal testen, muss aber deutlich schneller sein). Für das Überprüfen, welche Bereiche im Screenshot geändert sind, brauche ich ca. 8 ms (auch alter Entwicklungs-PC). Auch wenn das eigentlich schnell genug sein sollte, würde mich Dein Hinweis auf die Display Duplication API interessieren. Hast Du das tatsächlich mal getestet und wenn ja, dann gibt es schon eine Delphi Implementation dafür? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:35 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz