Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Übertragungsprotokoll für TSocket ??? (https://www.delphipraxis.net/148631-uebertragungsprotokoll-fuer-tsocket.html)

jokerfacehro 5. Mär 2010 12:07


Ü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 ?

SirThornberry 5. Mär 2010 12:26

Re: Übertragungsprotokoll für TSocket ???
 
Welche Delphiversion hat du denn?

jokerfacehro 5. Mär 2010 12:26

Re: Übertragungsprotokoll für TSocket ???
 
ich nutze Delphi 7 Enterprise

Sherlock 5. Mär 2010 12:29

Re: Übertragungsprotokoll für TSocket ???
 
zur Erinnerung: Das ganze NonVCL!

Sherlock

jokerfacehro 5. Mär 2010 12:35

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.
http://www.delphi-library.de/viewtop...er=asc&start=0


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.

sirius 5. Mär 2010 12:38

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)?

jokerfacehro 5. Mär 2010 12:41

Re: Übertragungsprotokoll für TSocket ???
 
ähm

kannn sein, dass ich dich falsch verstanden habe, sirius.

also in paketer wird der buffer ausgewertet:

Delphi-Quellcode:
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;
Das ist alles hier grad erst mal testweise hingeschrieben, deswegn auch Packets[0] ganz unten,
da ich eh erstmal nur ein Packet übertrage, nämlich das fürs bild

sirius 5. Mär 2010 13:01

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

jokerfacehro 5. Mär 2010 13:20

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:

jokerfacehro 5. Mär 2010 13:49

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 ???


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:12 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz