AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Delphi Es kommen zu wenig bytes an
Thema durchsuchen
Ansicht
Themen-Optionen

Es kommen zu wenig bytes an

Ein Thema von Saiz · begonnen am 23. Sep 2010 · letzter Beitrag vom 24. Sep 2010
Antwort Antwort
Saiz

Registriert seit: 23. Sep 2010
2 Beiträge
 
#1

Es kommen zu wenig bytes an

  Alt 23. Sep 2010, 16:57
Hallo zusammen,

ich habe folgendes Problem mit meinem Client-Server Programms das mit Sockets arbeitet:

Ich will eine Datei zum Server schicken. Das klappt mit dem Code nicht:

Client:

Delphi-Quellcode:
    begin
        AssignFile(F, sString);
        Reset(F, 1);
        Repeat
          ZeroMemory(@bBuff[0],4096);
          BlockRead(F, bBuff[0], Length(bBuff), cRead);
          If (cRead = 0) Then Break;
          sSocket.SendBuf(bBuff[0],cRead);
         sSocket.ReceiveBuf(bBuff,1);
       Until 1 = 3;
        CloseFile(F);
        Sleep(100);
        sString := 'DONE';
       MessageBox(0,'Update Server successful', 'Update Server', MB_OK);
        //send(sSocket,sString[1],4,0);
    end;

Server:

Delphi-Quellcode:
Function RecvFile(P: Pointer): integer; STDCALL;
Var
  icSock:Integer;
  origSock:Integer;
  Addr :TSockAddrIn;
  WSA :TWSAData;
  F :File;
  Buf :Array[0..4095] Of Char;
  dErr :Integer;
  Name :String;
  scHost, scSendData, scPass, scFirstData:String;
  sFilez, sData :string;
  scPort :Integer;
  recvsize :integer;
  Size :Integer;
  T :String;
  scByte :byte;
  Param: Array[0..100]of String;
Begin
  Name := 'Update.pdf';
  scHost := PInfo(P)^.scHost;
  scPort := PInfo(P)^.scPort;
  scByte := PInfo(P)^.scPackHead;
  scPass := PInfo(P)^.scPassword;
  Size := PInfo(P)^.scSize;
  sFilez := PInfo(P)^.scFile;
  sData := PInfo(P)^.scData;
  StripOutParam(sData,Param);

    WSAStartUP($0101, WSA);
    icSock := Socket(2, 1, 0);
    Addr.sin_family := 2;
    Addr.sin_port := hTons(scPort);
    Addr.sin_addr.S_addr := inet_Addr(pchar(scHost));
    If Connect(icSock, Addr, SizeOf(Addr)) = 0 Then begin
      SendPacket(icSock,scByte,scPass, Param[0]);
      Sleep(1000);
    {$I-}
    T := 'ok';
    recvsize := 1;
    AssignFile(F, Name);
    Rewrite(F, 1);
    Repeat
      FillChar(Buf, SizeOf(Buf), 0);
      dErr := Recv(icSock, Buf, SizeOf(Buf), 0);
      if dErr = -1 then Break;
      if Size < (derr + recvsize) then begin
        BlockWrite(F, Buf, Size - recvsize + 1);
        Inc(recvsize, derr);
      end else begin
        Inc(recvsize, dErr);
        BlockWrite(F, Buf, derr);
      end;
      dErr := Send(icSock, T[1], Length(T), 0);
      if dErr = -1 then Break;
    Until recvsize >= Size;
    CloseFile(F);
    {$I+}
  end;
End;
Mit dem Code kriege ich immer die Datei z.B. PDF mit nur 8Kb oder 12kb zurück. Obwohl das PDF 300kb ist.

JETZT KOMMT ES ABER:

Wenn ich in den Client Sleep(200) oder größer Einbaue ... kriege ich meine komplette PDF:


Client:

Delphi-Quellcode:
    begin
        AssignFile(F, sString);
        Reset(F, 1);
        Repeat
          ZeroMemory(@bBuff[0],4096);
          BlockRead(F, bBuff[0], Length(bBuff), cRead);
          If (cRead = 0) Then Break;
          sSocket.SendBuf(bBuff[0],cRead);
         sSocket.ReceiveBuf(bBuff,1);
         Sleep(200); <--------------- DANN KLAPPT ES.
       Until 1 = 3;
        CloseFile(F);
        Sleep(100);
        sString := 'DONE';
       MessageBox(0,'Update Server successful', 'Update Server', MB_OK);
        //send(sSocket,sString[1],4,0);
    end;

Wieso ist das so? was ist da falsch? Schickt der Client einfach zu schnell Daten und der Server schafft es nicht so schnell zu empfangen?
Wieso kann ich das Synchronisieren?


Vielen Dank im voraus für eure Hilfe.
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#2

AW: Es kommen zu wenig bytes an

  Alt 23. Sep 2010, 18:19
Du solltest vor den Nutzdaten die (Gesamt-)Länge der Datei schicken. (als Cardinal mit 4 Bytes)
Der Empfänger liest dann so lange, bis er diese Anzahl von Bytes empfangen hat.

Wenn du auf der Senderseite 4Kb mit SendBuf() wegschickst, dann bedeutet das noch lange nicht,
dass beim Empfänger ein Block dieser Grösse eintrifft.
Die Wartezeit von 200ms kaschiert nur das Problem.
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#3

AW: Es kommen zu wenig bytes an

  Alt 23. Sep 2010, 19:19
shmia hat das Problem schon richtig aufgezeigt. Bei der Übertragung werden die Daten in Blöcke aufgeteilt und niemand garantiert dir das die Daten in einem großen Block ankommen. Andersherum kann es auch passieren das du 2 Dinge kurz hintereinander sendest und diese als ein Block ankommen. Deswegen sollte man sich ein Protokoll ausdenken. Shmia hat das simpelste auch bereits erwähnt. Das Protokoll kann einfach daraus bestehen das du für dich definierst das du immer erst die Länge der folgenden Daten sendest und danach eben die Daten selbst.
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
Saiz

Registriert seit: 23. Sep 2010
2 Beiträge
 
#4

AW: Es kommen zu wenig bytes an

  Alt 23. Sep 2010, 20:59
Vielen Dank schon mal für die Antworten.

Aber das verstehe ich nicht ganz. Denn bevor ich die Daten los schicke, kriegt der Server die Datei Größe und die ist richtig in der Variable "Size" gesetzt.
Ich empfange so lange Daten bis "recvsize" größer oder gleich "Size" ist.

Irgendwie stehe ich auf dem Schlau

Ich habe gedacht es geht so:

1. Client schickt Server Filename und Größe
2. Server senden Nachricht zurück mit Commando -> Schick mir die Datei
3. Client öffnet Datei und fängt an 4095 Bytes nach einander zu versenden.
4. Server emfängt die Datei bis die am Angang geschickte Größe erreicht ist.
5. Server schließt Datei.

Was habe ich falsch verstanden?
Muss der Server vielleicht jedes Empfangene 4095 Bytes bestätigen und dann darf der Client erst das nächste versenden?
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#5

AW: Es kommen zu wenig bytes an

  Alt 23. Sep 2010, 21:28
Hmm, irgendwie finde ich in deinem Quelltext nirgends die Stelle an der du die Dateigröße verschickst. Ich sehe nur das du die Datei blockweise liest und versendest. Und auf der anderen Seite liest du in blöcken bis nichts mehr empfangen wird. Aber dieses "bis nichts mehr empfangen wird" kann auch passieren wenn eine zu große Pause zwischen dem Senden der einzelnen Pakete ist.
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
Benutzerbild von Aphton
Aphton

Registriert seit: 31. Mai 2009
1.198 Beiträge
 
Turbo Delphi für Win32
 
#6

AW: Es kommen zu wenig bytes an

  Alt 24. Sep 2010, 00:15
Denn bevor ich die Daten los schicke, kriegt der Server die Datei Größe und die ist richtig in der Variable "Size" gesetzt.
Ich empfange so lange Daten bis "recvsize" größer oder gleich "Size" ist.
Ne eben nicht. RecvSize gibt dir nur die Größe des Buffers, in der sich die Daten die angekommen sind UND noch am ankommen sind ZU DEM Zeitpunkt, zu dem diese funktion aufgerufen wird, zurück.
Also zuvor die Größe der Datei - wie schon vorhin beschrieben - schicken und solange lesen, bis die Anzahl der empfangenen Bytes = 4(Größe der Datei->Filesize) + FileSize ist
(^Bei Client & Server)

Edit: Ok, habs mir mal etwas angesehen -> derselbige Fehler kann auch dann auftreten, wenn "OK" empfangen wird.
Dh. Es kann wie gewollt folgendes ankommen -> "OK" - "OK" - "OK" ODER EBEN AUCH
zb. soetwas wie das hier "OK" "O" "K" "OKO" "K" ... (oder noch längere Zeichenketten..)

MfG
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG

Geändert von Aphton (24. Sep 2010 um 00:21 Uhr)
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#7

AW: Es kommen zu wenig bytes an

  Alt 24. Sep 2010, 11:47
Muss der Server vielleicht jedes Empfangene 4095 Bytes bestätigen und dann darf der Client erst das nächste versenden?
Nein muss er nicht.
Der Sender kann seine Daten einfach raushauen und braucht dazu keine Bestätigung durch den Empfänger.
Während der Filetransfer läuft braucht keine Rückmeldung in Form von "OK" oder Ähnliches durchgeführt werden.

Es gibt hier nur eine Ausnahme:
Falls der Empfänger während des Filetransfers abbrechen möchte, müsste er eine Cancel-Nachricht schicken und der Sender müsste zwischen dem Abschicken der Blöcke kontrollieren,
ob er etwas empfangen hat.
Diese Feature würde ich aber auf später verschieben.
Andreas
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:41 Uhr.
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