AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Delphi Spielwiese - SocketTest
Thema durchsuchen
Ansicht
Themen-Optionen

Spielwiese - SocketTest

Ein Thema von stahli · begonnen am 7. Okt 2016 · letzter Beitrag vom 24. Mär 2017
Antwort Antwort
Benutzerbild von stahli
stahli
Online

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.352 Beiträge
 
Delphi 11 Alexandria
 
#1

AW: Spielwiese - SocketTest

  Alt 28. Nov 2016, 14:46
Ich nutze das Paket jetzt etwas erweitert in einem realen Programm. Das macht auf meinem Win10-Rechner und Win10-Laptop auch schon einen sehr guten Eindruck.

Auf meinem dienstlichen Rechner (Win7 Prof, 32bit) werden im Client aber nicht alle Daten dargestellt. Teilweise funktioniert es, aber nicht vollständig oder nur kurze Zeit.
Eine TCP-Verbindung besteht zumindest anfangs mal.

Welche einfachste Möglichkeit gibt es, den TCP-Traffic von außen zu loggen (ohne selbst etwas einzubauen)?
Wenn ich sehen würde, ob überhaupt noch Nachrichten ausgetauscht werden, könnte ich das Problem vielleicht schon mal etwas eingrenzen.

Ich habe hier keine Adminrechte und kann daher nichts installieren.
Gibt es dennoch eine Möglichkeit, den Traffic etwas einzusehen?
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Aviator

Registriert seit: 3. Jun 2010
1.611 Beiträge
 
Delphi 10.3 Rio
 
#2

AW: Spielwiese - SocketTest

  Alt 28. Nov 2016, 16:46
Welche einfachste Möglichkeit gibt es, den TCP-Traffic von außen zu loggen (ohne selbst etwas einzubauen)?
Wenn ich sehen würde, ob überhaupt noch Nachrichten ausgetauscht werden, könnte ich das Problem vielleicht schon mal etwas eingrenzen.
Schau dir mal WireShark an. Damit kannst du den gesamten Traffic auf deiner Netzwerkkarte beobachten.

EDIT:

Ich habe hier keine Adminrechte und kann daher nichts installieren.
Oh zu spät gelesen. Sorry.
Aber vielleicht gibt es ja eine Version die als Portable genutzt werden kann.

EDIT 2: Ja auf der DownloadSeite gibt es eine Portable Version als 32bit Version.

Geändert von Aviator (28. Nov 2016 um 16:50 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli
Online

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.352 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Spielwiese - SocketTest

  Alt 29. Nov 2016, 08:43
Vielen Dank.

Ich habe mir jetzt aber doch ein eigenes provisorisches Logging eingebaut (aus Zeitgründen noch nicht fertig).
Ich kann schon mal sehen, dass beim Client nicht alles ankommt.
Wird irgendwas beim Server klemmen.
Mal schauen...
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#4

AW: Spielwiese - SocketTest

  Alt 29. Nov 2016, 18:43
Bei den non-blocking Sockets musst du beim Senden aufpassen:
Zitat von MSDN:
If no error occurs, send returns the total number of bytes sent, which can be less than the number requested to be sent in the len parameter.
Zitat von MSDN:
If no buffer space is available within the transport system to hold the data to be transmitted, send will block unless the socket has been placed in nonblocking mode. On nonblocking stream oriented sockets, the number of bytes written can be between 1 and the requested length, depending on buffer availability on both the client and server computers.
Also müsstest du gegebenenfalls nach einem nicht vollständigen MSDN-Library durchsuchensend()-Versuch manuell den Rest in einem/mehreren subsequenten send() Calls hinterherschicken.

Was zusätzlich immer passieren kann (blocking und non-blocking), dass die Daten eines einzigen send()-Aufrufs in mehreren recv()-Aufrufen ankommen. Irgendeine Form von Pakettrennung muss man also zwingend selbst implementieren (Längenbasiert oder anhand von Trennzeichen). Aber das machst du soweit ich mich erinnere ja indirekt mit deinen String-Listen.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli
Online

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.352 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: Spielwiese - SocketTest

  Alt 8. Dez 2016, 08:02
Ich habe den Übeltäter.

Längere Texte werden ggf. bei der Übertragung gesplittet.

Mein Handler hatte hier noch einen Bug und hat die unvollständigen Teile schon verarbeitet. Das Problem trat auf meinen 2 Rechnern nicht auf, aber bei allen anderen getesteten. Das lag wohl daran, wie die einzelnen Threads jeweils zeitlich zum arbeiten kommen.


Also falls das jemand nutzen will dann hier ein Bugfix:
Delphi-Quellcode:
function TsoConnectionStringList.GetNextSL: TStringList;
var
  C: Integer;
begin
  fCS.Enter;
  try
    if (fIndex < fItems.Count) then
    begin
      C := StrToInt(fItems[fIndex]);
      fItems[fIndex] := '';
      Inc(fIndex);
      Result := TStringList.Create;
      while (C > 0) do
      begin
        Result.Add(fItems[fIndex]);
        fItems[fIndex] := '';
        Inc(fIndex);
        Inc(fTransferCounter);
        Dec(C);
      end;
      if (fIndex >= fItems.Count) then
      begin
        fItems.Clear;
        fIndex := 0;
      end
      else
      begin
        if (fIndex > 1000) then
        begin
          while (fItems.Count > 0) and (fItems[0] = '') do
          begin
            fItems.Delete(0);
            Dec(fIndex);
          end;
        end;
      end;
    end
    else
      Result := nil;
  finally
    fCS.Leave;
  end;
end;
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli
Online

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.352 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Spielwiese - SocketTest

  Alt 22. Dez 2016, 12:21
Die letzte Änderung reicht doch nicht aus.

Also mein Konzept ist gut einsetzbar für kurze Stringlisten-Messages.
Wem das ausreicht, der kann das gut einsetzen.

Längere Stringlisten werden aber von den Sockets in 2 oder mehr Teilen übertragen und auf Grund der Zeilenumbrüche nicht immer korrekt zusammengesetzt.
Wer also auch längere Stringlisten übertragen will braucht eine alternative Lösung.

Ich bin daher dabei, die Stringlisten in Streams zu speichern und die Streams zu übertragen. Das hat auch den Vorteil, dass man die Streams bei Bedarf leichter komprimieren bzw. verschlüsseln kann.

Orientiert habe ich mich an folgendem Beitrag: http://www.delphipraxis.net/687499-post27.html

Jetzt habe ich das Problem, dass Read(...) manchmal feuert, Socket.ReceiveLength aber 0 ist und entsprechend keine Daten geladen werden können. Read(...) feuert aber später nicht noch einmal, so dass Daten verloren gehen.

Wenn ein Stream vollständig angekommen ist wird er wieder in eine StringList geschrieben und in eine Queue gehängt zur weiteren Verarbeitung durch Threads.
Kann sein, dass ich hier etwas verbockt habe, aber in der Nacht konnte ich da nichts mehr finden.
Eigentlich sollten die Verarbeitungsthreads ja die Eriegnisbehandlung im Mainthread nicht stören. Solange ich Strings übertragen hatte war das auch nicht der Fall.
(Blöderweise spinnt mein USB-Stick schon wieder, so dass ich hier gerade keinen Code dabei habe und ihn gerade nicht posten kann.)

Hat jemand so pauschal eine Idee, wie das Problem Socket.ReceiveLength=0 zu lösen ist?
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#7

AW: Spielwiese - SocketTest

  Alt 22. Dez 2016, 16:04
Hat jemand so pauschal eine Idee, wie das Problem Socket.ReceiveLength=0 zu lösen ist?
Der von dir verlinkte Code hat mehrere Schwächen:
  • Theoretisch ist es möglich, dass die Länge schon nicht in einem Stück ankommt
  • Wenn du zwei Streams hintereinander schickst, kann das letzte Paket von Stream 1 bereits die Länge und Daten von Stream 2 enthalten
Einfachste Vorgehensweise:
  1. Erstmal ALLE eingehenden Daten an einen Buffer (präziser: einer FIFO Datenstruktur) hinten anhängen
  2. Dann in einer Schleife alle vollständigen Pakete abarbeiten (Pseudo-Code):
    Delphi-Quellcode:
    while ((PacketSize = 0) and (BufferSize >= SizeOf(PacketSize)) or
      ((PacketSize > 0) and (BufferSize >= PacketSize)) do
    begin
      if (PacketSize = 0) then
      begin
        // Hier PacketSize vom Anfang des Buffers auslesen, dann alle Daten
        // im Buffer um SizeOf(PacketSize) nach vorne verschieben und schließlich
        // BufferSize um SizeOf(PacketSize) dekrementieren
      end;
      // Vollständiges Paket vorhanden
      if (BufferSize >= PacketSize) then
      begin
        // Hier Paket-Daten vom Anfang des Buffers auslesen, dann alle Daten
        // im Buffer um PacketSize nach vorne verschieben und schließlich
        // BufferSize um PacketSize dekrementieren
      end;
    end;
Durch diese Vorgehensweise solltest du alle Möglichen Fälle abdecken. Aus Performancegründen würde ich noch versuchen die Verschiebe- und besonders die Realloc Operationen des Buffers zu minimieren. Beispielsweise könntest du noch ein zustäzliches Feld BufferPos pflegen, mit dem du dir diese Aktionen sparst (müssten dann nur einmalig nach der Schleife ausgeführt werden, aber nicht bei jedem Durchlauf). Falls deine Pakete nicht in anderen Threads abgearbeitet werden, kannst du dir auch das Auslesen der Paketdaten sparen und deinem Paket-Handler einfach einen Zeiger auf @Buffer[BufferPos] zurückgeben, etc. Auch würde ich den Buffer nie komplett auf Null shrinken, sondern immer mindestens X-Byte alloziiert lassen, damit du bei kleineren Paketen im Optimalfall sogar komplett auf Realloc verzichten kannst.

Edit:
Achso und wie sieht deine Sende-Routine aus? Bei non-blocking Sockets kann MSDN-Library durchsuchenSend auch erfolgreich sein, aber trotzdem keine bzw. nicht alle Daten senden (wenn der Empfangsbuffer zu voll ist). Deshalb musst du hier in einer Schleife selbst dafür sorgen, dass alles verschickt wird. Bei den blocking Sockets kann das nicht passieren, da MSDN-Library durchsuchenSend dann einfach blockiert, bis im Empfangsbuffer wieder Platz ist und alle Daten gesendet werden konnten.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)

Geändert von Zacherl (22. Dez 2016 um 16:08 Uhr)
  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 20:28 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