Weshalb funktioniert der Sende Code nicht?

Alle Fragen zur Netzwerkkommunikation
Antworten
Pseudo
Beiträge: 21
Registriert: Fr 28. Sep 2012, 17:31

Weshalb funktioniert der Sende Code nicht?

Beitrag von Pseudo »

Hallo,

ich muss sehr große Dateien(>20 MB) senden. Und da die WSA (Windows Socket API) nicht mehr als 1MB annimmt, zerteile ich den String (ja, ich lade die Datei in einen String) in 1024 Stücke und schicke ihn. Jedoch habe ich nur zum Test, mal einen String mit 14 Zeichen gesendet und Empfangen, und es kommt nur Schwachsinn raus... Wo liegt der Fehler?

Code: Alles auswählen

function Send(CMD: String; FSocket: TSocket): Int64;
var
  SendLen: Int64;
  Len: Int64;
  CurSend: Integer;
const
  MAX_CACHE = 4;
begin
 Len := Length(CMD);
 SendLen := 0;
 CurSend := 0;
 while ((SendLen < Len) and (CurSend <> -1)) do begin
   If (Len - SendLen) < MAX_CACHE Then begin
 
   CurSend := Winsock.send(FSocket, CMD, (Len - SendLen), 0);
   Delete(CMD, 1  , CurSend);
   SendLen := SendLen + CurSend;
   end else begin
 
   CurSend := Winsock.send(FSocket, CMD, MAX_CACHE, 0);
   Delete(CMD, 1  , CurSend);
   SendLen := SendLen + CurSend;
 
   end;
 
 end;
 
 IF CurSend <> -1 Then
 Result := SendLen
 else
 Result := -1;   
end;

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Weshalb funktioniert der Sende Code nicht?

Beitrag von pluto »

Ich denke, es liegt wohl am "(Len - SendLen)" im ersten Teil der IF Anweisung. Lass dir mal mit ShowMessage oder writeln ausgeben, was da steht. Bestimmt ein Negativerwert.

Edit01: Entferne mal das Delete in der Ersten if Anweisung. Das kommt mir Spanisch vor.

Ich kann den Code leider nicht testen, da ich Linux verwende.
MFG
Michael Springwald

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Weshalb funktioniert der Sende Code nicht?

Beitrag von Socke »

pluto hat geschrieben:Ich denke, es liegt wohl am "(Len - SendLen)" im ersten Teil der IF Anweisung. Lass dir mal mit ShowMessage oder writeln ausgeben, was da steht. Bestimmt ein Negativerwert.

Für so etwas gibt es einen Debugger ...

pluto hat geschrieben:Edit01: Entferne mal das Delete in der Ersten if Anweisung. Das kommt mir Spanisch vor.

Stimmt. Die Positionsberechnung auf den gesamten Daten zu basieren ist sinnvoll -- diese dann hinterher zu löschen ohne die Postionsdaten zu ändern nicht mehr.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Pseudo
Beiträge: 21
Registriert: Fr 28. Sep 2012, 17:31

Re: Weshalb funktioniert der Sende Code nicht?

Beitrag von Pseudo »

Also der Grundgedanke war:

Ich schicke die ersten 4 Bytes (Hallo?), und lösche sie dann (o?), um dann in der nächsten Runde die nächsten vier zu senden, in jeder Runde prüfe ich ob vier da sind zu Senden, wenn nicht dann sende ich soviele wie da sind.

Danke für die Hilfe

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Weshalb funktioniert der Sende Code nicht?

Beitrag von pluto »

Ja. Aber im ersten Abschnitt der IF Anweisung macht es kein Sinn.
Wenn es weniger als 1024 Zeichen sind, brauchst du es nicht. Aber auch sonst macht es wenig Sinn.

Du kannst doch einfach die Position ändern? z.b. erst ist die Position 0 und dann 1024 und soweiter...
MFG
Michael Springwald

Pseudo
Beiträge: 21
Registriert: Fr 28. Sep 2012, 17:31

Re: Weshalb funktioniert der Sende Code nicht?

Beitrag von Pseudo »

Der noch zusendende Teil, muss ja nich durch 1024 teilbar sein, und somit muss ich schauen ob ich die nächsten 1024 sende, oder den Rest (z.B. 458 Bytes). Und wie mach ich das mit der Positionsänderung am besten?

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Weshalb funktioniert der Sende Code nicht?

Beitrag von pluto »

Beispiel:
Du brauchst doch nur den Rest auszurechnen. Wie groß ist CMD? was ist der Letzte Parameter in "Winsock.send(FSocket, CMD, MAX_CACHE, 0);"?

ich würde so vorgehen: Teile die Maximale Größe durch 1024 und nehme das Ergebnis mal 1024. Dann hast du dein Maximum Davon ziehst du die Aktuelle Position ab.
Du könntest es auch einfacher machen: Die Größe von CMD minus die Aktuelle Position.
Wie könnte CMD aussehen? können Strings Überhaupt größer als 1024 sein?
MFG
Michael Springwald

Pseudo
Beiträge: 21
Registriert: Fr 28. Sep 2012, 17:31

Re: Weshalb funktioniert der Sende Code nicht?

Beitrag von Pseudo »

sagen wir mal, CMD wäre 1600 Bytes groß, dann würde ich erstmal 1024 Bytes senden, und danach wieder versuchen 1024 zu senden... Das geht schief! Von daher muss diese Abfrage rein! Und wie komme ich an die Stelle zwischen dem 1024 und dem 2048 Zeichen?

pluto
Lazarusforum e. V.
Beiträge: 7178
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Weshalb funktioniert der Sende Code nicht?

Beitrag von pluto »

Du musst erst schauen, ob du 1024 Komplett senden kannst und wenn nicht, muss du es wie du es schon versucht hast, Stückweise machen. Hier mal ein Beispiel Code:
Jedoch wirst du ihn anpassen müssen:

Code: Alles auswählen

 
  ...
  StartIndex:=0; Len:=Length(CMD); Max:=1024;
  while True do begin // Entweder True oder False, damit komme ich immer durcheinander
    if StartIndex+Max >=Len  then begin
//     Kopiere den Rest: Len-StartIndex ergibt den Rest
      break; // Beende den Vorgang
    end
    else begin
      // Kopiere etwas zwischen StartIndex und Startindex+Max
      startIndex:=startIndex+Max
    end;
  end;
  ...
 

So in etwa würde ich es machen. Vielleicht hilft es dir weiter.
MFG
Michael Springwald

gocher
Beiträge: 298
Registriert: Di 23. Nov 2010, 23:41
OS, Lazarus, FPC: Ubuntu/Win, Lazarus trunk, FPC trunk
CPU-Target: 32Bit/64Bit
Wohnort: Geldern
Kontaktdaten:

Re: Weshalb funktioniert der Sende Code nicht?

Beitrag von gocher »

Ich würde es ungefähr so machen, mal so runter geschrieben, also nicht getestet!

Code: Alles auswählen

 
function send(const FileName:String; FSocket: TSocket): Int64;
const BUFFSIZE= 2048;
var
  pBuffer: Pointer;
  hHandle: Thandle;
  dwSize, dwBytesRead: dword;
begin
  result := 0;
  hHandle := CreateFile(pChar(FileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  if hHandle <> INVALID_HANDLE_VALUE then
  begin
    SetFilePointer(hHandle, 0, nil, FILE_BEGIN);
    dwSize := GetFileSize(hHandle, nil);
    repeat
      GetMem(pBuffer, BUFFSIZE);
      ReadFile(hHandle, pBuffer^, BUFFSIZE, dwBytesRead, nil);
      if FSocket <> INVALID_SOCKET then
        Send(FSocket , pBuffer^, dwBytesRead, 0);
      result := result + dwBytesRead;
    until (result >= dwSize);
  end;
end;
 
MfG Gocher
akt. Projekt: Webserver(HTTPS HTTP/2) mit integrierten CMS in Free Pascal - www.gocher.me

Antworten