![]() |
Übertragungsprotokoll für TSocket ???
Hallo,
ich habe ein Client-Server-System basierend auf dem TSocket per TCP erstellt.
Delphi-Quellcode:
Socket(AF_INET,
SOCK_STREAM, IPProto_TCP); das problem ist, das alt bekannte. wie schaffe ich es die daten richtig zu verpacken, sodass der empfänger damit ordentlic harbeiten kann. ich habe mir ein protokoll ausgedacht, das folgendermaßen aussieht: (die begriffe Frame und Packet sind nicht auf das OSI modell bezogen) jeder Frame hat 8192 bytes zuerst kommt ein header Frame: er besteht aus - GlobalID (2Byte) diese beschreibt das Paket, zu welchem mehrere Teile gehören, bei jedem Teilstück ist diese ID gleich - LocalID (2Byte) diese identifiziert das Teilstück an sich. - Command (2Byte) ist das auszuführende kommando - Daten (8186Byte) die ersten teile der daten dann folgen die Daten Frames: -GlobalID (2Byte) -LocalID (2Byte) diese wird bei jedem Frame inkrementiert -Daten (8188Byte) der letzte Frame hat die LocalID 1111 1111 1111 1111 (0xFFFF) (erstmal vernachlässigbar für das folgende beispiel) wodurch das ende des paketes angegeben wird. so sieht ein beispiel aus wie ich die daten sende:
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var st:TFileStream; str:string; buffer:array[1..8192] of Byte; begin st:=TFileStream.Create('C:\Dokumente und Einstellungen\Admin\Eigene Dateien\server\1670478.jpg',fmOpenRead); st.Position:=0; str:=#00#01#00#01#00#04+IntToStr(st.Size)+#13#10+'C:\'+#13#10+'pic.jpg'+#13#10; //frameheader und erste daten Send(FConnectSocket[0],str[1],Length(str),0); buffer[4]:=$00000; while st.Position<st.Size do begin //FillChar(buffer,8192,#0); buffer[1]:=$0000; buffer[2]:=$0001; buffer[3]:=$0000; buffer[4]:=buffer[4]+$0001; st.Read(buffer[5],8188); Send(FConnectSocket[0],buffer[1],Length(buffer),0); end; st.Free; end; das funktioniert allerdings nicht ganz. der server scheint alles richtig zu senden, zumindest steht alles richtig in buffer drin das problem ist jetzt folgendes: beim Client kommt der Header Frame richtig an und wird auch korrekt verarbeitet. ich empfange immer genau 8192 Bytes; jeder weitere Datenteil der ankommt, hat auch den header dran und wird zum paket hinzugefügt. allerdings variiert die komplette datengröße das bild ist 650KB groß und es kommen mal 140KB an, mal 300, mal 640. so empfange ich per WndProc:
Delphi-Quellcode:
var buffer:string;
FD_READ: begin setLength(buffer,8192); count:=recv(wp,buffer[1],8192,0); {setLength(buffer,count); packeter(buffer);} while count>0 do begin setLength(buffer,count); packeter(buffer); setLength(buffer,8192); count:=recv(wp,buffer[1],8192,0); end; writeln(IntToStr(Length(Packets[0].Data))); //writeLn(ntohs(socketaddr.sin_port)); //OnRead(wp,buffer); PostQuitmessage(Msg); //-- WMOnAsyncServerData(wp, lp); end; aber nicht das richtige. was mache ich falsch ? |
Re: Übertragungsprotokoll für TSocket ???
Welche Delphiversion hat du denn?
|
Re: Übertragungsprotokoll für TSocket ???
ich nutze Delphi 7 Enterprise
|
Re: Übertragungsprotokoll für TSocket ???
zur Erinnerung: Das ganze NonVCL!
Sherlock |
Re: Übertragungsprotokoll für TSocket ???
ja das ganze soll auf der client seite nonVCL sein.
der server kann VCL nutzen. deswegen will ich auf der Client seite auch keine Streams nutzen. hab hier mal reingeschaut, ist allerdings sehr unübersichtlich. ![]() und ich hab ma nen chat auf string basis mit terminator geeschrieben. allerdings will ich jetzt daten und befehle, also teilweise Bytes teilweise strings übertragen und für Dateiübertragung brauche ich ja ein anderes verfahren, deshalb diese Variante, fallsihr eine bessere möglichkeit habt das mit TSocket zu realisieren, könnt ihr die gern an bringen. auf jedenfall soll das ganze nonVCL sein und TSocket nutzen. |
Re: Übertragungsprotokoll für TSocket ???
Du musst die Pakete unterschiedlicher Größe sammeln und dann immer schauen, ob eins deiner Frames fertig ist. Das ist dir bewusst (kam jetzt nicht so heraus)?
|
Re: Übertragungsprotokoll für TSocket ???
ähm
kannn sein, dass ich dich falsch verstanden habe, sirius. also in paketer wird der buffer ausgewertet:
Delphi-Quellcode:
Das ist alles hier grad erst mal testweise hingeschrieben, deswegn auch Packets[0] ganz unten,
type TPacket = record
GlobalID:Word; LocalID:Word; CMD:Word; Data:string; end; procedure packeter(buffer:string); var check:boolean; i:integer; begin if Copy(buffer,3,2)=#0#1 then begin setLength(Packets,Length(Packets)+1); Packets[Length(Packets)-1].GlobalID:=Byte(buffer[1])+Byte(buffer[2]); Packets[Length(Packets)-1].LocalID:=Byte(buffer[3])+Byte(buffer[4]); Packets[Length(Packets)-1].CMD:=Byte(buffer[5])+Byte(buffer[6]); Delete(buffer,1,6); Packets[Length(Packets)-1].Data:=buffer; end else begin {check:=false; for i:=0 to Length(Packets)-1 do if Packets[i].GlobalID=Byte(buffer[1])+Byte(buffer[2])then begin check:=true; break; end; Delete(buffer,1,4); if check then} Delete(buffer,1,4); Packets[0].Data:=Packets[0].Data+buffer; end; end; da ich eh erstmal nur ein Packet übertrage, nämlich das fürs bild |
Re: Übertragungsprotokoll für TSocket ???
Ja, aber das Socket zerschneidet dir doch deine Pakete. TCP achtet nur darauf, dass Sie in der richtigen Reihenfolge ankommen.
Was ist, wenn gerade an der Stelle gebrochen wird, wo auch das Bild mit #0#1 weitergeht? Du musst den gesamtn Datenstrom erstmal sammeln:
Delphi-Quellcode:
setlength(tempbuffer,8192);
len:=recv(s,tempbuffer[1],length(tempbuffer),0); setlength(tempbuffer,len); buffer:=buffer+tempbuffer; //analysiere buffer auf fertiges Paket //wenn Paket fertig, bearbeite Paket und lösche so viele Bytes von buffer-Anfang, iwe Paket groß war |
Re: Übertragungsprotokoll für TSocket ???
so
ich habs mal so gemacht und mir die länge ausgeben lassen: Edit: jede zeile steht für eine FM_READ MSG die abgearbeitet wurde. insgesamt sind trotzdem nicht alle daten angekommen. :wall: :mrgreen: 28 8192 16384 8192 0 024576 49152 0 0 32768 65536 8192 0 0 163840 0 0 196608 0 0 0 0 ich versteh nicht warum er nicht gleich alle daten einliest, sondern in unterschiedlichen abständen ne neue MSG macht :gruebel: |
Re: Übertragungsprotokoll für TSocket ???
ich verstehs einfach nicht.
die anzahl der insgesamt empfangenen daten variiert ständig bis zu 100kb. wie kann sowas zustande kommen ??? lese ich den FileStream falsch ein ??? |
Re: Übertragungsprotokoll für TSocket ???
Zitat:
![]() lg. Astat |
Re: Übertragungsprotokoll für TSocket ???
sooooooooooooooooooooooooooooooooooooooooooooooooo oooooooooooooooooooooooooooooooooooooooooo
problem erkannt, allerdings noch keine lösung gefunden es zu beheben: ich habs jetzt hinbekommen, es lag am sender:
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var st:TFileStream; str:string; buffer:array[1..8192] of Byte; i:integer; begin st:=TFileStream.Create('C:\Dokumente und Einstellungen\Admin\Eigene Dateien\data\backer\server\txt.txt',fmOpenRead); st.Position:=0; i:=8192; //FillChar(str,8192,#0); //str:=#00#01#00#01#00#04+IntToStr(st.Size)+#13#10+'C:\'+#13#10+'txt.txt'+#13#10; //Send(FConnectSocket[0],str[1],Length(str),0); setLength(str,i); while st.Position<st.Size do begin //FillChar(buffer,1024,#0); if st.Size-st.Position<8192 then begin ///----> wichtig i:=st.Size-st.Position; setLength(str,i); end; st.Read(str[1],i); Send(FConnectSocket[0],str[1],Length(str),0); end; st.Free; end; jetz empfängt er beim ersten senden die richtig anzahl von daten. wenn ich allerdings ein 2. mal das gleiche sende sind es etwa 8KB daten zu viel, als wenn noch etwas im chache vom server steht. wie kann ich die restlichen daten löschen ? Edit: irgendwie hauts immer noch nicht hin, jetzt fehlen genau 8192 byte @Astat danke für den eitnrag, werds mir ma anschaun Edit2: ich hab jetzt gemerkt, wenn ich debugge und sende kommt alles an, lasse ich das programm einfach durchlaufen fehlen immer 8192byte |
Re: Übertragungsprotokoll für TSocket ???
so ^^
ic hhabs jetz hinbekommen: ich sende jetzt so: Datengröße|Befehl|Daten.................. Datengröße besteht aus 4 Byte, somit ist die maximale datengröße auf 4GB begrenzt. Befehl besteht aus 2Byte und wird gleich extrahiert um schneller entscheiden zu können was mit den restliche daten passieren soll. Dann folgen die Daten. Der Client empfängt das erste teilstück und speichert sich die datenlänge ab. dann empfängt er so viele daten, bis die angegeben datenmenge erreicht ist, dann schneidet er diese ab, speichert sie zusammen mit datengröße und befehl in einem paket und löst OnExecute aus, wo der befehl dann verarbeitet wird. überschüssige daten bleiben im speicher und sind gleichbedeutend mit dem anfang eines neuen paketes. |
Re: Übertragungsprotokoll für TSocket ???
Hallo jokerfacehro, ein JA, wenn die Daten korrekt für jeden Socket (Client-Verbindung) aufbereitet wurden.
D.h. wenn viele Clients am Server, braucht man für jeden Client einen separaten Empfangsbuffer, der so zu behandeln ist, wie du geschrieben hast. Globaler Socket Empfangsbuffer --> Dispatch --> zum Client-Buffer. lg. Astat |
Re: Übertragungsprotokoll für TSocket ???
ähm ?
zur erläuterung: das ganze läuft am client ab. der server ist vcl und bekommt, doch eh den socket mitgeliefert für jeden client, sodass ich direkt im event unterscheiden kann, welcher client gerade spricht und kann das ganze im record zusammenspeichern |
Re: Übertragungsprotokoll für TSocket ???
Zitat:
Hätte doch genauer lesen sollen, sorry. :wall: lg. Asat |
Re: Übertragungsprotokoll für TSocket ???
Zitat:
:cyclops: :mrgreen: kein problem :D beim datenspeichern mach ich es anders, ich schreibe die datei on the fly, so brauhc ich nicht alles zwischen speichern, das hat mir 250mb ram gespaart und lieber mit blockwrite anstatt mit write schreiben ^^ |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:07 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