Speicherbereich reservieren... Welche größe?

Anfängerfragen zum Programmieren mit PureBasic.
Toshy
Beiträge: 713
Registriert: 22.03.2005 00:29
Computerausstattung: Computer und Strom vorhanden
Wohnort: LK Wolfenbüttel

Re: Speicherbereich reservieren... Welche größe?

Beitrag von Toshy »

Nach testen mit Netlimiter kann ich den Hinweis von STARGATE nur bestätigen. SendNetworkData() gibt NICHT die gesendeten Daten zurück, sondern was in irgen einen Buffer gelegt wurde.
Die Daten die man auf einmal sendet, dürfen aber nicht unendlich viel sein. 10 MB mit SendNetworkData() machen kein Problem, 100 mb gehen nicht.

Ich bin bisher auch von was anderem ausgegangen. Das tuen wohl alle, denn es ist total unlogisch.
Denn in der Hilfedatei stehen zwei Dinge die genau auf das von PMV genannte hinweisen.

1.
welche tatsächlich gerade gesendet wurden.
Es steht klar da, das der Rückgabewert der ist, der gerade gesendet wurde. Wenn dem nicht so ist, dann ist mein halber aktuell erstellter Code im Grunde sinnlos. super.
2.
Bei UDP-Verbindungen beträgt die maximale 'Länge' 2048. Bei TCP-Verbindungen beträgt die maximale 'Länge' 65536.
Das sagt ja, das man maximal 65536 Bytes senden darf (anscheined aber mehr). Und dann geht man davon aus, das der Buffer voll wäre. Der Buffer der halt wartet bis die Daten weg sind.

Wenn SendNetworkData() nicht die tatsächlich gesendete Menge zurückliefert, weiß man ja gar nicht, wann man wieder was senden sollte.
Aktuell habe ich nur eine 7 kbyte-Onlineverbindung (ja, so wenig, router ist hin, läuft nur über USB-stick) ich kann jetzt 10-mb senden und er sagt, die daten raus. würde ich wissen, das der buffer noch voll ist (64000 kb), dann würde ich natürlich nicht auf mehreren verbindungen weiter daten senden.
Da haut doch irgend etwas gar nicht hin. böse böse.

Steht auf jeden Fall anders in der Hilfe. Ich bin jetzt echt erschrocken.
Und normal ist das ja der sinn von TCP. Der Sende kann es ja an sich schon wissen, denn TCP überprüft ja (da heißt auch beim Sendendten) ob die Daten komplett und in der richtigen Reihenfolge angekommen sind, wenn nicht werden Pakete nachgeliefert (soweit ich verstanden habe). Das Sendende "Betriebssystem" weiß also schon ob die Daten auch angekommen sind (bedeutet nicht, das sie auch richtig verarbeitet wurden), also wäre es logisch, wenn das wie es in der Hilfe steht an PB weiter geliefert wird.

Die Hilfe muß also umgeschrieben werden in
Rückgabewert

Gibt die Anzahl an Bytes an, welche welche in den Ausgangsbuffer gelegt wurden Ist der Wert nicht gleich dem Parameter "Länge" ist vielleicht der Buffer voll oder ein anderer Fehler ist aufgetreten. -1 deutet ebenfalls auf einen Fehler hin.
Anmerkung mit den UDP- und TCP-Buffer kann gestrichen werden

Man man man, ich bin ja sinnvoller Weise wie auch PMV davon ausgegangen, das die Ausführung wartet bis die Daten gesendet wurden. ist ja gar kein Problem. für paralleles Arbeiten gibt es ja Threads.

Also wir müssen über Andre echt Fred dazu bringen dringend die Netlib Fehlerfrei und neu zu machen. PB und die Netlib (besonders wichtig für mich) sollen einem ja genau das ganze kompleziertere basteln mit den Socket abnehmen.
Zuletzt geändert von Toshy am 08.06.2012 01:25, insgesamt 1-mal geändert.
1. Win10
PB6.1
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7028
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Speicherbereich reservieren... Welche größe?

Beitrag von STARGÅTE »

Also wir müssen über Andre echt Fred dazu bringen dringend die Netlib Fehlerfrei und neu zu machen.
PB und die Netlib (besonders wichtig für mich) sollen einem ja genau das ganze kompleziertere
basteln mit den Socket abnehmen.
Jemanden "unter Druck" zu setzen wird dir/uns nicht weiter helfen.
Fest steht, mit der altuellen Situation (die nicht unbedingt perfekt ist) ist es sehr wohl möglich,
sichere und fehlerfreie Netzwerk-Anwendungen und Spiele zu schreiben (wie ich ja selber bewiesen habe, wie ich denke).

Das SendNetworkData() warten sollte, bis es angekommen ist, ist nicht unbedingt sinnvoll oder logisch.
Schließlich wartet ReceiveNetworkData() auch nicht "direkt" auf den Empfang von zB 10KB,
sonden kopiert auch nur auf dem Eingangspuffer zum eigenen Programm.

Wie PMV schon anmerkte ist TCP ja sicher, soll heißen, wenn man SendNetworkData() verwendet hat,
kann man davon ausgehen, dass die Daten auch "früher oder später" beim Clienten sind,
außer die Verbindung wird getrennt.
______

Hier mal meine Ansätze zum senden (welche ich auch in meinen Spielen/Anwendungen nutze):

Für "normal größe" Daten (in meinem Fall Pakete) verwende ich eine Prozedur,
welche SendNetworkData nutzen, und bei unvollständigem Versand,
in abstand von einigen Millisekunden SendNetworkData() erneut mit dem Rest ausführt.
Also eine prozedur die u.u die Programmausführung kurz anhält.

Für "sehr größe" Daten verwende ich ein zusätzlichen Komunikations-Port,
aufdem mich die Clienten fortlaufend darüber unterrichten, wie viele Bytes angekommen sind,
von dem was versendet wurde. Erst bei übereinstimmung wird erneut SendNetworkData() ausgeführt.
In diesem Fall muss das ganze in einem Thread ausgelagert werden,
da der Sendevorgang auch mal mehrere Minuten dauern kann.
______

Ich habe mir halt mit der Zeit mein Include zusammen geschrieben,
was mit das "Netzwerk-Leben" erleichtert.
Und wenn man etwas unbedingt haben möchte, wäre das auch der erste Weg,
und nicht der zum PB-Team.
Vermutlich denke ich so, weil ich viele Jahre mit 3.3 geschrieben habe,
und die Funktion von neueren Versionen selber geschrieben habe.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Toshy
Beiträge: 713
Registriert: 22.03.2005 00:29
Computerausstattung: Computer und Strom vorhanden
Wohnort: LK Wolfenbüttel

Re: Speicherbereich reservieren... Welche größe?

Beitrag von Toshy »

Unter Druck setzen klingt so negativ.
Aber nach Jahren muß man doch mal was machen.
Langsam wundere ich mich nicht mehr, warum meine alten Codes manchmal eigenartiges Verhalten aufweisen.

Ich habe jetzt sogar bemerkt, das SendNetworkData() sehr wohl den Code blocken kann.
Baue ich nach dem ersten senden der 10 MB (die noch versendet werden) noch eine neue Verbindung auf und sende dort wieder 10 BM und dann noch eine Verbindung usw., dann gibt es immer zurück, das die daten GESENDET wurden, stimmt ja wohl nicht. Aber was schlimmer ist, irgend wann, bei mir aktuell ca. bei der 5. ten verbindunge stockt das programm bei SendNetworkData(). Ist der Buffer irgend wie voll (grob 50 mb) über 5 verbindungen, dann geht nichts mehr. es wird auch kein -1 zurück geliefert, das Programm stoppt bei SendNetworkData(). Was noch schlimmer ist, wenn ich die übertragunsbegrenzung von netlimiter aufhebe passiert es manchmal, das das programm weiter läuft und weiter sendet, meißt hängt es bei mir aber bis in alle ewigkeit. und damit meine ich genau die funktion Sendnetworkdata. manchmal kommt es wenn der Buffer (bei ca. 50 mb) voll ist, einfach keine neue Verbindung aufgebaut werden kann. mal ja, mal nein.
Da ist überhaupt keine verläßlichkeit drinn.

SICHERE Programme lassen sich damit ja gar nicht machen. Ich hatte damals was zum datei syncronisieren und bakups machen geschrieben. dabei wurden auch über 7 kbyte verbindungen daten übertragen. war kein problem, da wurde dann halt nebenbei über wochen viel versendet. jetzt aber erst verstehe ich, warum es dann öfter zu hängern kam. wenn SendnetworkData() sporadisch hängt.... das geht ja gar nicht.
Und wenn man angeblich 50 mb versendet hat, und das nicht stimmt, aber auch kein bufferfehler kommt, dann geht das auch nicht. man kann dannja nicht mal bei der gegenseite überprüfen was schon da ist. die verbindung ist dann ja blockiert.
Und da ich gerade DSL-Ausfall für einige ZEit habe, ist mir das erst jetzt richtig aufgefallen.
Wie PMV schon anmerkte ist TCP ja sicher, soll heißen, wenn man SendNetworkData() verwendet hat,
kann man davon ausgehen, dass die Daten auch "früher oder später" beim Clienten sind,
außer die Verbindung wird getrennt.
Und genau das sollte ja etwas anders sein, wen die meldung kommt, versendet, sollte das auch so sein. Und Buffer voll sollte auch kommen, wenn angekündigt.
Ich habe hier wie geschrieben aktuell 7 kb übertragungsrate im download (upload ca. das selbe. muß mal schauen). und 50 mb lassen sich übertragen, angeblich. aber ich , müßte jetzt 2 stunden warten um rausfinden zu können, ob die Daten wirklich angkommen sind. und verhindern kann ich das nicht. es gibt ja kein "Buffer voll" mit -1 wie es sein sollte bei ca. 64 kbyte.
Hier mal meine Ansätze zum senden (welche ich auch in meinen Spielen/Anwendungen nutze):

Für "normal größe" Daten (in meinem Fall Pakete) verwende ich eine Prozedur,
welche SendNetworkData nutzen, und bei unvollständigem Versand,
in abstand von einigen Millisekunden SendNetworkData() erneut mit dem Rest ausführt.
Also eine prozedur die u.u die Programmausführung kurz anhält.

Für "sehr größe" Daten verwende ich ein zusätzlichen Komunikations-Port,
aufdem mich die Clienten fortlaufend darüber unterrichten, wie viele Bytes angekommen sind,
von dem was versendet wurde. Erst bei übereinstimmung wird erneut SendNetworkData() ausgeführt.
In diesem Fall muss das ganze in einem Thread ausgelagert werden,
da der Sendevorgang auch mal mehrere Minuten dauern kann.
Ich hatte damals und jetzt etwas ähnliches, ich mache es nur optimierter neu. dazu arbeite ich auch mit Threads. ich bin noch nicht ganz fertig, aber damals war es ählich (und nutze es heute noch). Hauptprozess, und dann je einen Thread für Eventauslesen und datenempfang am server und als cliente (also 2 threads), einen für das senden der daten. also 3 Thread plus hauptprozess. dabei ist der Sendethread so konzepiert, das ich den mehrfach aufrufen kann (also mehrere sendethreads) und die dann selbständig die daten auf den Verbindungen senden. meine eigenen "sendnetworkdata"-routinen legen dabei die daten in einem eigenen buffer vorläufig ab. das sollte ersten sein um die 64 000 zu umgehen und auch große dateimengen im hintergrund senden zu können (meißt im ram, aber auch datei als buffer).
nur.... sende ich jetzt z.b. eine datei, wird die (über SendNetworkData()) in maximal 64 kb blöcken gesendet (der last wegen teste ich mit 2 byte-blöcken). und da ich gerade das dsl-problem habe, kam es mir gelegen, dann über das netzt auch mal auf meinen homeserver was zu senden. ups.... 50 mb in einer sekunde raus, und dann geht erst mal nichts. stunden warten um eine anweisung zu senden... ne ne.

einen zweiten Port an sich, also eine zweite Verbindung ist bei mir an sich nicht nötig gewesen. auf Grund eines eigenen Protokolls (das ich jetzt nur noch mal neu machen wollte) wird die Datei bzw. die Daten nicht in eins durchgesendet. in Paketen und an der Gegenstelle automatisch zusammen gesetzt. dadurch ist es absolut kein Problem zwischendurch andere Dinge zu senden, anweisungen, Chattexte oder sonst was. nur wenn es kein "Buffer voll" gibt und Daten im Ausgangspuffer auch mal Stunden benötigen bis sie ankommen ohne einen Fehler auszulösen... dann ist das nicht mehr wirklich zu händeln.

Ich sende also schon in Blöcken und habe ein eigenes Protokoll, da ber wo ohne das mein Programm es mitbekommen kann 50 mb in einem Buffer liegen und bei langsamen Verbindungen nichts passiert oder sogar die Funktion hängen bleibt... da kann nur das PB-Team etwas machen. Und vor allem soweit ich das in den Foren sehe, da schon teils seit JAHREN nach gefragt wird.

Allerdings das SendNetworkData() auch mal hängen kann ist wohl bisher nur mir augefallen.

Nochmals zum Schluß...
ich bin zwar nicht fertig mit dem code, ein teil aber ließ sich testweise auführen. und obwohl testweise 5 thread auf 5 verbindungen gesendet werden solten, hängten auf einmal ALLE Threads. .... was soll man da dann noch machen. dabei war ich so auf meine Codestruktur stolz, da an sich leistungsfähig.
Ich überlege gerade, ob ich nun komplett alles einmotte :-(

Nachtrag:

Code: Alles auswählen

; server

If InitNetwork() = 0
  MessageRequester("Error", "Can't initialize the network !", 0)
  End
EndIf

Port = 6844
*Buffer = AllocateMemory(10000)

If CreateNetworkServer(0, Port)
  Debug "server gestartet"
  Repeat
    SEvent = NetworkServerEvent()
    If SEvent
      ClientID = EventClient()
      Select SEvent
        Case #PB_NetworkEvent_Connect
          Debug "neuer client"
        Case #PB_NetworkEvent_Data
          ergebnis = ReceiveNetworkData(ClientID, *Buffer, 10000)
        Case #PB_NetworkEvent_Disconnect
      EndSelect
    EndIf
  Until Quit = 1 
  MessageRequester("PureBasic - Server", "Click to quit the server.", 0)
  CloseNetworkServer(0)
Else
  MessageRequester("Error", "Can't create the server (port in use ?).", 0)
EndIf
End   

Code: Alles auswählen

; client
;

If InitNetwork() = 0
  MessageRequester("Error", "Can't initialize the network !", 0)
  End
EndIf

Port = 6844
*buffer = AllocateMemory(1024*1024*100)

For i = 1 To 10
  Debug "versuche Verbindung aufzubauen"
  ConnectionID = OpenNetworkConnection("127.0.0.1", Port)
  If ConnectionID
    Debug( Str(i) + ". Verbindung wurde aufgebaut")
    Debug "versuche daten zu senden"
    Ergebnis = SendNetworkData(ConnectionID, *buffer, 1024*1024*10)
    Debug("daten gesendet = " + Str(ergebnis))
  Else
    Debug "Verbindung wurde nicht aufgebaut"
    ;MessageRequester("PureBasic - Client", "Can't find the server (Is it launched ?).", 0)
  EndIf
Next
Debug "ende"
MessageRequester("PureBasic - Client", "Ende", 0)
;CloseNetworkConnection(ConnectionID)
mit dem Code und einer langsamen Verbindung ODER besser mit dem Programm netlimiterhttp://www.netlimiter.com und die Verbindung auf 5 kbyte/sek gesetzt löst der obige Code unregelmäßig Programmhänger aus. löse ich die 5 kbyte/sek begrenzung nach einiger Zeit wieder, so das der Rest der Daten schnell versendet werden kann, werden auf einmal super schnell (localhost) die daten aus dem Buffer gesendet, aber Sendnetworkdata() hängt. aber das passiert unregelmäßig. schließe ich den Server, dann "bricht" auch SendNetworkData() ab bzw. geht weiter.
Ganz genau habe ich noch nicht rausgefunden, wann das passiert. manchmal geschieht das etliche Versuche nacheinander, dann einige Zeit gar nicht mehr. Aber ich kann den hänger immer mal wieder "nachproduzieren". Aktuell hängt es schon seit Minuten, obwohl keine Daten mehr übertragen werde.
1. Win10
PB6.1
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7028
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Speicherbereich reservieren... Welche größe?

Beitrag von STARGÅTE »

Habe mir deinen Code jetzt nicht weiter angesehen (mach ich morgen).
Allerdings hängt der Code nicht bei Sendnetworkdata() sondern bei mir immer bei OpenNetworkConnection()
Jemehr Verbindungen aufgebaut werden, desto "schwerer" geht der Verbindungsaufbau.
Aber alle Sendnetworkdata() werden sofort ausgeführt.

Gegen das u.a. "nicht Threadsicher" hat cxAlex ein umfangreiches Include geschrieben.
Vielleicht hast du es schon gesehen, vllt aber auch nicht.
Vielleicht hilft es dir ja weiter.

PS: Damit du mich nicht falsch verstehst, ich bin nicht gegen Verbesserungen seites PB, aber von Seiten des Teams gibt und gab es vermutlich andere Schwerpunkte. Bleibt abzuwarten was der neue Thread im englischen Forum so hervor bringt.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Toshy
Beiträge: 713
Registriert: 22.03.2005 00:29
Computerausstattung: Computer und Strom vorhanden
Wohnort: LK Wolfenbüttel

Re: Speicherbereich reservieren... Welche größe?

Beitrag von Toshy »

Hab dich schon verstanden.
Nur obwohl Fred und PB toll sind und an sich viel gemacht wird, Netzwerk ist so lange schon wichtig und wird es immer mehr. Und da geschieht nichts. Und weiterhin... da gibt es wirklich Probleme. Sie treffen nur nicht in jeder Situation zu.


Bei mir hängt es beim Sendnetworkdata()
"versuche daten zu senden" wird noch angezeigt, weiter geht es aber nicht (bis server beendet wir).
Verbindungen an sich können beir mir hunderte oder tausende ohne Problem aufgebaut werden (anderer testcode).

Der code oben ist ja gar nichts besonderes, ist nur beim testen "entstanden". aber der wird zum testen geändert.

ich habe jetzt mit netlimiter die verbindungsgeschwindigkeit entweder auf 1 kbyte/sek (localhost / mein computer) eingestellt. und wenn ich das so lange genug stehen lasse (mist, zeit nicht gemerkt, aber sagen wir mal 20 minuten) und dann das limit aufhebe... kurz viel datenempfang (und senden) und dann .... tot. ich werde morgen auch noch etwas testen. aber trotz das meine threads dadurch blockiert werden, wede ich wohl meinen "richtigen Code" mal weiter entwickeln

die Vorlage von cxAlex hatte ich mal gesehen. aber nicht weiter verwendet. Easynetworkmanager oder so. das download war dann irgend wann nicht mehr verfügbar. irgendwo hatte ich aber noch eine Version gefunden. Soweit ich mich erinnere, war die zwar Threadsicher, aber das ist ja an sich einfach. da braucht man thoretisch nur ein einziges Mutex. Meine Threads aber blockieren sich fast nie gegenseitig. gleichzeitiges Senden usw. kein problem. na ja, wenn PB da jetzt nicht die Probleme machen würde ;-)
Und es bassiert ja auch der networklib und nicht direkten Apiaufrufen. Bleibt also bei selben Problemen :-(

Nachtrag:
Ich habe jetzt noch weiter gestet, ich habe jetzt in kleinen Happen gesendent. Immer wenn der Buffer voll ist, dann blockiert SendNetworkData. Es wird halt nicht wie erwartet ein -1 zurück gegeben. das bedeuet kurz gesagt, sendet man schneller Daten, also die Netzwerkverbindung verträgt hängt das Programm früher oder später bei SND() bis wieder platz im Buffer ist (oder ganz).
Wenn ich jetzt das senden in kleinen und größen Blöcken beobachtet.
Wie im obigen Beispiel bei großen blöcken stoppt dann sendnetworkdata irgend wann (zum testen 1 kbyte/sekunde bandbreite). selbes auch bei kleinen blöcken (siehe code unten). Der unterschied liegt darin, wen EIN SendNetworkData-Aufruf zu lange wartet (Zeit oder Bedinung kenne ich nicht) verläßt PB die Funktion gar nicht mehr.

Code: Alles auswählen

Code lasse ich jetzt doch erst mal weg
--------- --------- --------- --------- ---------
2. Nachtrag:
Eine Lösung habe ich gefunden.
Ich erinnerte mich an mein Problem von "letztens" und dem Thema "[uralt Bug?]ReceiveNetworkData-Aufruf ohne anliegende Daten". - chris - schrieb dann die Auflösung des Problems. auf Clientseite (wohl nicht auf Serverseite) ist der "blocking mode" als standart eingestellt. Das gilt dann wohl nicht nur für den Empfang, sondern auch für das Senden.Rufe ich nach dem Connect am Clienten einfach

Code: Alles auswählen

socket = ConnectionID(ConnectionID)
    arg = 1
    ioctlsocket_(socket, #FIONBIO, @arg)
auf, dann hängt SendNetworkData() nicht mehr und liefert -1
Puh... Aber das bedeutet, jeder sollte am Clienten IMMMER
den code zum "Entblocken" nutzen. Ich erstelle eh für mich und alle gerade eine NetworkHinweisdatei.. da kommt das dann einfach mit rein.

Leider bleibt dann wohl das problem bestehen, das die Daten trotz dem Hinweis in der Hilfe nicht gesendet sind. Allerdings hängt das Programm nicht mehr. gut.
Ich werde das Verhalten aber noch mal neu testen.
So.. dann mal rann an die nächsten 100 Networkprobleme ;-)
1. Win10
PB6.1
Antworten