Große Bilder mit ServerSocket verschicken
-
Hi zusammen!
Ich habe es ja dank eurer Hilfe endlich hinbekommen Bilder mit dem ClientSocket/ServerSocket zu verschicken. (siehe hier: Das Leidige Thema: Socket->ReceiveBuf und SendStream )Das geht mit kleinen Bildern ganz gut, aber sobalt das Bild größer wird (genaue größe konnte ich nicht feststellen, aber z.B. 32*32 geht, 1024*768 nicht) geht das versenden nicht. (Fehlermeldung Ungültiges Bitmap).
Beide Bilder habe ich einfach in Paint gezeichnet, also liegen die bilder in den gleichen Formaten vor.
Woran kann das mit dem Fehler liegen?
Ich hatte mir überlegt, wenn es keine richtige Lösung gibt, das große Bild einfach in 10 gleichgroße Teile zu verkleinern, aber diese Lösun gefällt mir nicht.
Schonmal großes Danke im Voraus,
J0
-
Vermutlich leidest du unter einem ähnlichen Problem wie unser freund mit seinem Ethernet-Target das steuerzeichen mitsendet. Vermutlich ist nicht das Ganze Bitmap übertragen wenn der erste Event ausgelöst wird...
-junix
-
versteh ich nicht
wieso kommt ein kleines Bild an (maximal 84*84 pixel) aber ein großes Bild nicht?
J0
-
Das kömmt schon an aber in mehreren tranchen.... Die musst du dann selber zusammensetzen...
-junix
-
aso! verstanden! aber wie mach ich das?
Ich bin jetzt auf JPG umgestiegen, da kommt dieser Fehler nicht mehr, aber das Bild kommt nur zum teil an, (die ersten 5 Y-Pixel * die ersten 500 X-Pixel kommen an, und verinzelt noch welche), aber der Rest ist nur Grau.
Und es kommt der JPEG-Fehler #52 (siehe diesen thread, hab neu aufgemacht, da er nur indirekt was mit dem prob zu tun hat: JPEG Fehler #52 / Fehlerindex von TJPEGImage
Ich weiss, das Problem is schlecht beschrieben, ich weiss einfach nicht wie ich´s besser ´beschreiben soll.
Trotzdem danke,
J0
-
Du solltest ein Protokoll einführen und damit Anfang und ende der Bildübertragung markierst und dann liest du solange die bytes in den stream bis das Ende vorbei gehupft ist... weisst du wie ich meine?
-juni
-
Noch ein Beitrag zum Thema Protokollentwicklung: TServerSocket
-junix
-
danke, ich mach das mal so wie beschrieben!
J0
-
hmm ich hab das grade verstanden, wie das gemeint ist: so habe ich das bisher gemacht, nur ein bisschen anders:
Als erstes wird die größe geschickt.
Daraufhin wird bool Streambool auf true gesetzt.Der server wartet ein bisschen und schickt dann den Stream.
Dieser wird dann mit der (vorher) empfangenen größe entsprechend verarbeitet.Das is t doch das Selbe, oder hab ich was missverstanden?
Wenn ich den Stream mittels Stream->Size auf 30000 stelle, kommt dieser Stream 1a an, is halt nur abgehackt, weil die tatsächliche größe ca. das 11 fache ist.
Kann ich auch irgendwie anschließende die zweiten 30000 'Streamteile' schicken?
Weil dann währe das problem ja gelöst! Einfach for Schleife mit Stream->Size / 30000 machen und dann klappts!J0
-
Original erstellt von J0:
Der server wartet ein bisschenRein stilistisch in Sachen Protokolldesign eher etwas schlecht... So Timing-dinger würd ich nie umgehen... Ich würde einfach die Länge mit einem bestimmten Zeichen abschliessen und dann solange den Stream einlesen bis die Anzahl zugehörigen Bytes erreicht ist...
-junix
-
ich versteh das nicht ganz:
wo ist der unterschied zwischen Socket->ReceiveLength und wenn ich den Wert vorher schicke? Ausser wenn der Stream fehlerhaft ankommt, dann is das was anderes.Und wie kann ich einen Stream solange einlesen bis ein Wert erreicht wurde?
So?:
for ( int i = 0; i < StreamLaenge; i++) { //Stream einlesen (Wie?) } Image1->Picture->Bitmap->LoadFromStream(Stream);
Oder wie meinst du das?
J0
-
Oke, nochmals langsam zu mitschreiben für analphabeten (-;
Du hast folgendes Problem: TCP/IP-Packages sind von der Länge her begrenzt. Ausserdem wird der Event von den TWinSockets ausgelöst, nachdem das erste Byte angekommen ist (da ja der Socket nicht wissen kann wann ein Datenstrom abgeschlossen ist).
Angenommen du versendest ein Bild mit der Grösse von 10kByte. Dann kommt das erste Byte an, der Event wird ausgelöst. Bis allerdings dein Receive-Code ausgeführt wird, kommen vielleicht 4kByte an. Liest du dann die Länge der zu empfangenden Daten aus, gibt dir dieses nur 4kByte zurück. Es fehlen also noch 6kByte. Das Event wird - nach dem Auslesen - wieder ausgelöst. Vielleicht sind es diesmal 6kByte die im Verlauf der Empfangsoperation angekommen sind. Die werden danna uch ausgelesen. Erst jetzt ist das Bild komplett übertragen.
Was kannst du dagegen nun unternehmen?
Du musst zwischen den Socket und deine Anzeigeschicht noch eine Schicht einführen die dein persönliches Protokoll unterstützt. Sprich das Bild darf erst als übertragen angenommen werdne, wenn 10kByte übertragen sind und nicht erst 4kByte.
Wenn du jetzt erst die Länge sendest (10240) gefolgt von einem ":" zum beispiel bevor du die Bilddaten sendest, dann kannst du beim ersten Empfangen feststellen wie gross die Übertragung des Bildes sein wird.
Sowas:
10240:<10kByte Bild-Daten>Du liest ein, bis du einen ":" erkennst. Du kannst den eingelesenen Wert dann StrToInt() wandeln und kennst dann die Länge die eingelesen werden sollen. Du gibst das Bild dann solange nicht frei wie die Bytes nicht angekommen sind.
Etwas umständlich erklärt. Ich hoff du kommst trotzdem mit.
-junix
-
ok, jetzt hab ich´s verstanden!
danke, ich werde es nachher mal versuchen umzusetzten, hab im mom pc-verbot, darf erst heude abend, muss mich deshalb kurzfassen.
Danke,
J0
-
Ich habe es jetzt so gemacht, aber es kommen nie mehr als 8 KB (8192
an.
Kann da nicht auch irgendwie ein einstellungsfehler sien? weil wenn ich texte die größer als 8 KB groß sind, kommen die auch nur verstümmelt an.oder peile ich das einfach nicht?
Ich soll doch einfach die größe des streams empfangen,warten bis die empfangene Länge == Der vorher geschickten größe sind und dann laden. Da die zu verschickene Größe immer gleich ist (immer das gleiches Bild für den Test) ahbe ich das so gemacht:
// a = integer, Streambool = bool a = 15360; //15 KB while (a > Socket->ReceiveLength()) { Application->ProcessMessages() ; Streambool = false; } if(Streambool == true) { TJPEGImage *Screenshot = new TJPEGImage(); Streambool = false; Form1->Caption = "Was empfangen"; //int CharsToReceive_int = Socket->ReceiveLength(); BYTE *Buffer_BYTEp = new BYTE[a];//CharsToReceiveInt Socket->ReceiveBuf(Buffer_BYTEp, a); Stream->Position = 0; Stream->Write(Buffer_BYTEp, a); Stream->Position = 0; Screenshot->LoadFromStream(Stream); Screenshot->SaveToFile("Screenshot.jpg"); delete [] Buffer_BYTEp; Form2->Screenshot->Picture->Bitmap->Assign(Screenshot); delete Screenshot; }
Is das so richtig?
Oder falsch?J0
-
Falsch... Schmeiss die while{} weg und lass einfach den Event mehrfach aufrufen...
-junix
-
Vielen vielen herzlichen Danke!
Ich hab´s jetzt hinbekommen, der Fehler lag daran, dass ich immer mit dem empfangenem Stream den bisher empfangenen Stream überschrieben hab und an der while-schleife.
Nochmal vielen Dank,
J0