Autor |
Beitrag |
Dolognio
Hält's aus hier
Beiträge: 12
|
Verfasst: Fr 03.11.06 11:26
Hi @ all.
Ich habe hier im Forum gelesen wie ich in einen Stream ein Identifikationsmerkmal schreiben kann, um zu erkennen, was für ein Datentyp sich in dem Stream befindet. Das klappt auch ohne Compilerfehler.
Meine Frage ist jetzt allerdings: Wie kann ich den Stream nach Empfang wieder so aufteilen, dass erst der erste Teil ausgelesen wird mit dem Merkmal, und dann der Rest dem Datentyp entsprechend? Ich kann mir da absolut nichts drunter vorstelln.
Thx schonmal.
|
|
Udontknow
      
Beiträge: 2596
Win7
D2006 WIN32, .NET (C#)
|
Verfasst: Fr 03.11.06 11:58
Hallo!
Du musst nicht aufteilen. Du ermittelst mit einem Aufruf von
Delphi-Quelltext 1:
| Stream.ReadBuffer(ID,SizeOf(ID)); |
das Identifikationsmerkmal. Anschliessend reagierst du.
Delphi-Quelltext 1: 2: 3: 4:
| if ID=ID_JPG then Picture.LoadFromStream(Stream); if ID=ID_Text then Memo.Lines.LoadFromStream(Stream); |
Erst wenn du "hinter" den JPG-Daten auch noch andere Blöcke sendest, wird es schwieriger. Dann musst du einen temporären Stream hinzunehmen und zusätzlich in den Originalstream auch noch die Größe des Blocks schreiben, damit die Blöcke auseinanderzuhalten sind.
Cu,
Udontknow
|
|
Dolognio 
Hält's aus hier
Beiträge: 12
|
Verfasst: Fr 03.11.06 16:17
OK, thx, ich probier des mal so. Mla schauen ob ich des hinkrieg^^.
Cya.
PS: Thread lass ich für evtl weitere Fragen zum Thema ma noch offen bzw. unmarkiert.
|
|
Dolognio 
Hält's aus hier
Beiträge: 12
|
Verfasst: Fr 03.11.06 18:11
Hmm, also funzt doch noch nicht wie gewünscht, ka was jetzt wieder los ist. Erst ma der Code:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43:
| const ID_String = 0; const ID_Stringlist = 1;
procedure Testsenden; var sl: TStringlist; stream1, stream2: TMemoryStream; ID: integer; begin sl:= TStringlist.Create; Stream2:= TMemoryStream.Create; sl.Sorted:= false; sl.Clear; sl.BeginUpdate; try sl.add('string1'); sl.add('string2'); sl.add('string3'); sl.add('string4'); sl.add('string5'); sl.add('string6'); sl.add('string7'); sl.add('string8'); sl.EndUpdate; sl.SaveToStream(stream2);
stream1:= TMemoryStream.Create; try ID:=ID_Stringlist; Stream1.WriteBuffer(ID,SizeOf(ID)); try stream1.CopyFrom(stream2,stream2.Size) finally stream2.Free; MainFrm.TCPClient.SendStream(stream1); end; finally stream1.Free; end; finally sl.Free; end; end; |
Ich dachte egtl ich hab alles richtig gemacht, find kein Fehler, außer mn muss im Zusammenhang mit einer Stringliste noch was andres beachten beim Speichern in Stream. Jedenfalls bringt der Debugger zur Laufzeit den Fehler "Stream read error!" in der oben markierten Zeile.
Hoffentlich weißt du noch weiter 
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Fr 03.11.06 18:25
Moin!
Du mußt Stream2 auch wieder "zurückspulen".  So: Stream2.Position := 0;
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
Martok
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Fr 03.11.06 18:31
Oder statt Stream2.Size 0 angeben:
Delphi-Quelltext 32:
| { ... } stream1.CopyFrom(stream2,0); |
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
Dolognio 
Hält's aus hier
Beiträge: 12
|
Verfasst: Fr 03.11.06 23:38
Danke, jetzt klappts endlich, hätt ich in der Delphi-Hilfe geschaut über stream.copyfrom(), hätt ich gewusst dass ich ne 0 einfügen muss^^.
Wenn ich jetzt allerdings 2 verschiedene Merkmale in einen Stream einbauen muss, gilt dann das, was UDontKnow vorhin ma gesagt hat?
Udontknow hat folgendes geschrieben: |
Erst wenn du "hinter" den JPG-Daten auch noch andere Blöcke sendest, wird es schwieriger. Dann musst du einen temporären Stream hinzunehmen und zusätzlich in den Originalstream auch noch die Größe des Blocks schreiben, damit die Blöcke auseinanderzuhalten sind.
|
Und wenn ja, wie sieht dass denn dann aus? Was für Blöcke??? Und temporärer Stream ist TMemoryStream oder?
|
|
Udontknow
      
Beiträge: 2596
Win7
D2006 WIN32, .NET (C#)
|
Verfasst: Sa 04.11.06 21:59
Hier die grobe Vorgehensweise. Ich gehe davon aus, daß jeder "Block" eine ID und eine Size mitgibt. Für jeden Block wird dann ein Stream bereitgestellt und die Funktion VerarbeiteBlock aufgerufen
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34:
| procedure VerarbeiteBlock(ID:Integer; Size:Integer; Stream:TStream); begin end;
procedure VerarbeiteBloecke(Stream:TStream); var ID:Integer; var Size:Integer; var TempStream:TMemoryStream; begin While Stream.Position<Stream.Size do begin Stream.ReadBuffer(ID,SizeOf(ID)); Stream.ReadBuffer(Size,SizeOf(Size));
TempStream:=TMemoryStream.Create; try TempStream.Size:=Size; TempStream.CopyFrom(Stream,Size); TempStream.Position:=0; VerarbeiteBlock(ID,Size,TempStream); finally TempStream.Free; end; end; end; |
Cu,
Udontknow
|
|
Dolognio 
Hält's aus hier
Beiträge: 12
|
Verfasst: Sa 04.11.06 23:38
Also sry, aber ich werd aus deinem Code nich schlau.
Was versteht man denn überhaupt unter einem "Block"?
Und ich denk ma dass deine beiden Prozeduren zum lesen des gesendeten Streams da sind.
Wie aber speicher ich einen solchen Stream ab?
Einfach
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39:
| var sl: TStringlist; TempStream1, TempStream2, SLstream: TMemoryStream; ID: integer; begin sl:= TStringlist.Create; SLstream:= TMemoryStream.Create; try sl.SaveToStream(SLstream);
TempStream2:= TMemoryStream.Create; try ID:= ID_Stringlist; Stream1.WriteBuffer(ID,SizeOf(ID)); try TempStream2.CopyFrom(SLstream,0); TempStream1:= TMemoryStream.Create; try TempStream1.CopyFrom(TempStream2,0); finally SLStream.Free;
finally TempStream2.Free;
end; finally MainFrm.TCPClient.SendStream(TempStream1); TempStream1.Free; end; finally sl.Free; end;
end; |
?? Oder wie sonst?
Und wie gibt man einem "Block" (was auch immer das jetzt ist) ID und Size mit?
|
|
Udontknow
      
Beiträge: 2596
Win7
D2006 WIN32, .NET (C#)
|
Verfasst: So 05.11.06 17:33
Nun, ein Block ist für mich eben ein Paket zusammenhängender Daten.
Beispiel:
Du hast ein Chatprogramm geschrieben, über das du mal Text, mal aber auch ein Bild senden kannst. Nun tritt es ab und zu auf, daß Pakete aneinanderhängen, diese müssen also von dir auseinandergehalten werden. Das erreichst du, indem du die Struktur eben wie beschrieben aufbaust. Immer wenn der User ein Bild senden will, werden zuerst das Merkmal für "Bild", dann die Anzahl der Bytes für das Bild und anschliessend die Daten des Bildes gesendet. Die Empfangsroutine kann anhand des Headers (ID und Groesse) eben erkennen, wo ein Block endet und der nächste beginnt.
Cu,
Udontknow
|
|
Dolognio 
Hält's aus hier
Beiträge: 12
|
Verfasst: Mo 06.11.06 00:30
Hmm, also mit Streams muss ich mich glaub erst ma richtig befassen. Hab da noch nich so den Durchblick.
Hab mir daher jetzt auch was andres überlegt, wie ich 2 Merkmale in einen Stream schreiben kann.
Hier der Code:
Sender:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36:
| procedure Testsenden; var sl: TStringlist; stream1, stream2: TMemoryStream; ID: integer; begin sl:= TStringlist.Create; Stream2:= TMemoryStream.Create; sl.Sorted:= false; sl.Clear; sl.BeginUpdate; try
sl.EndUpdate; sl.SaveToStream(stream2);
stream1:= TMemoryStream.Create; try ID:= 15;
Stream1.WriteBuffer(ID,SizeOf(ID)); try stream1.CopyFrom(stream2,0) finally stream2.Free; MainFrm.TCPClient.SendStream(stream1); end; finally stream1.Free; end; finally sl.Free; end; end; |
und
Empfänger:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34:
| const ID_StringList = '1'; const ID_String = '2';
const ID_Frame1 = '1'; const ID_Frame2 = '2'; const ID_Frame3 = '3'; const ID_Frame4 = '4'; const ID_Frame5 = '5';
procedure TForm1.TCPServerInput(Connection: TSimpleTCPConnection; Stream: TStream; var DisposeStream: Boolean); var sl: TStringList; TypID, FrameID: char; ID: integer; h: string; begin stream.ReadBuffer(ID,sizeof(ID)); h:= inttostr(ID); TypID:= h[1]; FrameID:= h[2];
if TypID = ID_StringList then begin sl:= TStringList.Create; try sl.LoadFromStream(stream); if FrameID = ID_Frame5 then Frame5.ListBox1.Items.Assign(sl); finally sl.Free; end; end; end; |
Ist vielleicht nicht so sauber, aber funktioniert. Trotzdem DANKE für eure Geduld mir das alles näherzubringen!! 
|
|