NetworkServerEvent() und #PB_NetworkEvent_File

Für allgemeine Fragen zur Programmierung mit PureBasic.
Toshy
Beiträge: 713
Registriert: 22.03.2005 00:29
Computerausstattung: Computer und Strom vorhanden
Wohnort: LK Wolfenbüttel

NetworkServerEvent() und #PB_NetworkEvent_File

Beitrag von Toshy »

>_<

Hi.

Ich hatte bisher nie SendNetworkFile() genutzt und damit auch nicht #PB_NetworkEvent_File.
Es paßt mir einfach von der Art her nicht. #PB_NetworkEvent_File habe ich zur Sicherheit natürlich abgefangen und eine eventuell datei in eine Dummydatei gespeichert. Es kann ja sein, daß eine Verbindung die nicht von meinem programm aufgebaut wird eine Datei liefert.
Ich hatte mir ansonsten darüber keine weiteren Gedanken gemacht und bin davon ausgegangen, das es sich beim Dateisenden um einen Teil des (TCP/)IP-Protokolls handelt. Irgendwie so etwas.
Da ich gerade meine threadbasierten Netzwerkroutinen ganz neu schreibe und da ganz genau auf Struktur und "sicherheit" im Programmcode achte, habe ich mal etwas getestet. Und soweit ich das sehe handelt es sich bei #PB_NetworkEvent_File und "sendnetworkfile" nichts weiter als um ganz normale Rohdaten wie auch bei #PB_NetworkEvent_Data. Es wird nichts weiter gemacht als als eine immer gleiche 8 Byte lange "Bytekette" gefolgt von einem long mit Inhalt der Dateigröße und dann gefolgt von den Dateidaten gesendet.

Nun besteht ja das Problem, das rein zufällig genau diese ersten 8 Bytes mit Daten übereinstimmen die ich erhalte. Zwar ist das unwahrscheinlich, aber nicht unmöglich.
Sicher nicht so super pralle. Wenn dem wirklich so ist, sollte man das in der Hilfe vermerken.

Denn dann kann man diesen Fehler ja "umgehen".
Entweder muß man darauf achten das bei eigenene Programmen nie der Wert 4993443410339512912 übermittelt wird. Was aber nicht einfach ist, da ich nicht weiß wie überwacht wird. Und man dann nach JEDEM byte überprüfen müßte, ab dort der quadwert nicht dem obigen Wert entspricht.
Einfacher und wie ich es wohl machen werde ist, bei einem #PB_NetworkEvent_Data-Evemt einfach die daten mit "receivenetworkdata()" auslesen. Ein gewissen Problem gibt es da aber schon. Da ich dann ja auch nicht sicher weiß ob es wirkich eine Datei oder "der Zufall" ist kann ich mir nicht sicher sein beim auslesen der Daten in Bezug auf die Länge. Ich lese dann einfach die länge ab position 9 aus, aber falls es nun doch "das zufällige Quad" war, dann wäre ich vielleicht unendlich lange auf alle daten, da sei nicht kommen. da es bei #PB_NetworkEvent_File aber im Gegensatz zu _Data nur einmal ein Event gibt, weiß ich noch nicht wie ich das sicher abhandeln soll.

Weiß jemand wie das intern genau abläuft und wie man sich da verhält?
Prüft pb beim Empfang nach jedem byte, nach jedem Long oder wie auch immer ob der Wert übereinstimmt?

Ich empfinde das als ein echtes Problem, selbst wenn es nur relativ unwahrscheinlich oder extremst selten eintritt.

Ach ja, bisher habe ich das nur den Empfang am Server getestet.

Gruß
Toshy

Nachtrag:
Auweia, nicht mal das ganz normale verwenden von "sendnetworkfile" klappt immer wenn die Pakete vielleicht häpchenweise oder so ankommen bzw. wenn der server irgendwie langsam reagiert. böse böse Falle.
Um das zu testen könnte ihr die beiden Vorlagen aus der Networklib nutzen. ihr müßt nur eine zeile ändern, den rest in beiden dateien so lassen.
In der NetworkClient.pb müßt ihr nur nach "sendnetworkstring()" zusätzlich noch "sendnetworkfile()" aufrufen, nehmt damit es sicher klappt eine kleine datei, ein paar Kilobyte groß.
Server starten, client starten und die Datei kommt nie als "dateievent" an.
Das liegt daran, das der nach den Stringdaten gleich die Dateidaten im Buffer liegen, nun kommt ein Dataevent. Da man ja nicht weiß wie viele Daten angekommen sind, werden im Beispiel bis 1000 Bytes ausgelesen, damit aber auch schon der Anfang der "Dateidaten". Und das wars dann mit "dateiempfang".
Der Dateiempfang an sich schein nur dann zu klappen, wenn die ERSTEN 8 Byte im TCP buffer mit dem obigen Wert überein stimmen. Dadurch kann es im Grunde nur selten klappen. Und es erhöht dafür auch die Wahrscheinlichkeit, das der Wert getroffen wird.

Ich bin jetzt wirklich mal gespannt, wie ich das Problem sicher ausschließen kann. Vermutlich gar nicht, nur "bestmöglich". :freak:

2. Nachtrag:
Vielleicht gibt es eine Möglichkeit um das Problem mit dem Dateiempfang zu umgehen. Aber dazu müßte die ASM oder Winsockspezialisten etwas schreiben.
Da der Data und Fileempfang an sich das selbe ist, braucht man an sich nichts weiter zu machen, als beim Fileevent nichts auszulesen. Aber man müßte dann nach "Case #PB_NetworkEvent_File" einfach "manuell" ein "DataEvent" auslösen. Also wenn möglich in der "Socketverarbeitung des Betriebssystems" oder in PB an der Stelle die das DataEvent auslöst einfach "nachträglich" das event auslösen. dann könnte man das ganz normal weiter verarbeiten. (nur darauf achten, das dadurch nicht parallel dazu wieder ein FileEvent ausgelöst wird. Wäre auch nicht so schlimm, dann müßte man halt nur nach dem Event mindestens ein Byte auslesen.
1. Win10
PB6.1
Benutzeravatar
helpy
Beiträge: 636
Registriert: 29.08.2004 13:29

Re: NetworkServerEvent() und #PB_NetworkEvent_File

Beitrag von helpy »

Toshy hat geschrieben:#PB_NetworkEvent_File habe ich zur Sicherheit natürlich abgefangen und eine eventuell datei in eine Dummydatei gespeichert. Es kann ja sein, daß eine Verbindung die nicht von meinem programm aufgebaut wird eine Datei liefert.
In diesem Fall würde ich dem Client die Verbindung trennen (CloseNetworkConnection). Wer sich nicht an die Hausordnung des Servers hält, bleibt draußen!
Windows 10
PB Last Final / (Sometimes testing Beta versions)
Toshy
Beiträge: 713
Registriert: 22.03.2005 00:29
Computerausstattung: Computer und Strom vorhanden
Wohnort: LK Wolfenbüttel

Re: NetworkServerEvent() und #PB_NetworkEvent_File

Beitrag von Toshy »

Das ist leider keine Alternative.
Erstens ist das eine unsaubere Lösung und zweitens hat das wie ich schrieb nichts mit "Hausordnung" zu tun. Es ist nur eine Frage des Zufalls. So unwahrscheinlich es vielleicht sein mag, ergibt irgend eine 8-Byte Zeichefolge mitten in den Daten den Wert (#SendNetworkFile=)4993443410339512912, dann kann es zu einem hänger kommen.
Wie geschrieben, recht unwahrscheinlich (es sei denn, die 8 Bytes find nicht zufällig von Fred gewählt und hätten so eine höhere Wahrscheinlichkeit vorzukommen - z.B. Textzeichen in Form eines Wortes - hab das nicht getestet), aber dennoch kann man das ja nicht ignorieren.

Ich hoffe daher, in kürze ließt das einer der Socket oder PB(interna)experten.

So, ich mache mich dann mal wieder an meine Threadstrukturüberlegungen. Kopf dampft immer wieder beim Nutzen der Networklib auß mehreren Threads.

Nachtrag:
Ok, die Bytefolge ist zum Glück kein Begriff / Wort und daher eher zufällig zu treffen.
Da es sich aber dennoch um die Abkürzung von Begriffen handelt steigt die Wahrscheinlichkeit wieder.
"PBMGSFLE". Sicher bin ich mir nicht was es bedeutet (bei PBMSGFLE wäre ich mir recht sicher), aber vermutlich "PureBasicMassaGeSFiLE" (das mgS kommt mir komisch vor, daher nicht sicher).
Da aber wird das Problem selbst zum Problem, wenn auch nur auf wenigen seiten wird genau die Abkürzung bezüglich PB behandelt. Man könnte also keinen eigenen HTML-Downloader basteln der die Seiten sicher runter lädt. hehe
Durch die Suche nach PBMGSFLE habe ich jetzt wenigstens rausgefunden, daß dies schon einige wenige "rausgefunden" haben. ist ja nicht schwer. Löst bzw. Umgeht "das Problem" aber nicht.

Im Grunde stellt sich die Frage, was verhindert nach einem "NetworkFileEvent" und wenn man die Daten NICHT ausliest, das dann erneut Events eintreffen bzw. normale Events. .... Wo ich es jetzt schreibe... da habe ich eine Idee... aber das Test ich heute Abend.
1. Win10
PB6.1
Sirius-2337
Beiträge: 71
Registriert: 29.05.2010 20:55

Re: NetworkServerEvent() und #PB_NetworkEvent_File

Beitrag von Sirius-2337 »

Toshy hat geschrieben: Im Grunde stellt sich die Frage, was verhindert nach einem "NetworkFileEvent" und wenn man die Daten NICHT ausliest, das dann erneut Events eintreffen bzw. normale Events. .... Wo ich es jetzt schreibe... da habe ich eine Idee... aber das Test ich heute Abend.
Vielleicht war das ja auch deine Idee, aber man kann auch nach einem NetworkFileEvent mit ReceiveNetworkData die Daten empfangen.
Das heisst du kannst einfach sowas wie "Case #PB_Network_Data, #PB_Network_File" schreiben um deine Daten zu empfangen. Solange du nicht irgendwann selber SendNetworkFile verwendest sollte das keine Probleme machen.

Hier noch der Beweis das es Funktioniert

Code: Alles auswählen

InitNetwork()
*Buffer = AllocateMemory(1000)
CreateNetworkServer(0, 6832)

;Daten Senden
ConnectionID = OpenNetworkConnection("127.0.0.1", 6832)
SendNetworkString(ConnectionID, "PBMGSFLE - aabbccddeeff")
CloseNetworkConnection(ConnectionID)

Repeat
    
  SEvent = NetworkServerEvent()

  If SEvent
  
    ClientID = EventClient()

    Select SEvent
    
      Case #PB_NetworkEvent_Data
        MessageRequester("PureBasic - Server", "Client "+Str(ClientID)+" has send a packet !", 0)
        ReceiveNetworkData(ClientID, *Buffer, 1000)
        MessageRequester("Info", "String: "+PeekS(*Buffer), 0)

      Case #PB_NetworkEvent_File
        MessageRequester("PureBasic - Server", "Client "+Str(ClientID)+" has send a file via the network !", 0)
        ReceiveNetworkData(ClientID, *Buffer, 1000)
        MessageRequester("Info", "String: "+PeekS(*Buffer), 0)

    EndSelect
  EndIf
  
  Delay(1)
  
ForEver
Dark
Beiträge: 93
Registriert: 24.08.2007 20:36
Kontaktdaten:

Re: NetworkServerEvent() und #PB_NetworkEvent_File

Beitrag von Dark »

Dies ist leider nur ein weiteres Problem der Netzwerklibrary.

Insgesamt müsste die Netzwerklibrary in folgenden Punkten überarbeitet werden:
  • fehlende Unterstützung des TCP - Disconnect Events beim Client hinzufügen
  • virtuelle UDP "Verbindungen" entfernen - regelmäßig werden Anfänger dadurch verwirrt, das es bei UDP, dem Namen nach, irgendwelche Verbindungen gibt. Dieser Ansatz macht es auch unmöglich ein P2P System zu programmieren, bei dem Verbindungen, durch NATs, mit Hilfe von Hole Punching hergestellt werden. CreateUDPSocket(), BindPort(), SendNetworkData(IP, Port, Data), CloseUDPSocket() und das normale ReceiveNetworkData() würden reichen um eine universelle UDP Library zu erstellen.
  • IPv6 Support fehlt
  • Es gibt keine Möglichkeit eine Liste von IPs zu einer DNS Adresse erhalten. Hat ein Server mehrere IP Adressen wie z.B. Google, so könnte man einfach die nächste IP probieren, falls ein Server nicht erreichbar ist. Hierzu muss man aber die Befehle des Betriebssystems nutzen.
  • Bei SendNetworkString() die versendeten Zeichen/Bytes zurückgeben oder den Befehl gleich ganz entfernen. Viele nutzen den Befehl ohne zu bedenken, das ggf. nicht alle Daten gesendet werden.
  • #PB_NetworkEvent_File entfernen oder die Möglichkeit geben es abzuschalten
Das hört sich nach recht viel Arbeit an, aber im Endeffekt sind dies alles keine großen Änderungen. Ich habe vor einiger Zeit selbst so eine Lib in C++ geschrieben und das geht recht schnell. Die meisten Nutzer von PB, die professionelle Netzwerkanwendungen schreiben, nutzen meistens ihre eigenen Netzwerklibs. Hier wäre eigentlich Fred gefragt, aber wenn ich bedenke, wie sehr er sich um das Disconnect Event in den letzten Jahren gekümmert hat, so würde ich für die nächste Zeit nicht zu viel Hoffnung haben.
Vielleicht ändert sich das ganze ja mal, wenn IPv6 von mehr Internet Providern unterstützt wird und er gezwungen ist einige Änderungen vorzunehmen.

Dark
Benutzeravatar
Bisonte
Beiträge: 2476
Registriert: 01.04.2007 20:18

Re: NetworkServerEvent() und #PB_NetworkEvent_File

Beitrag von Bisonte »

Dark hat geschrieben:[...] wenn IPv6 von mehr Internet Providern unterstützt wird [...]
Laut Golem.de war die offizielle Einführung des Standards am 6.6.2012 (zum 2. mal)
nur in unseren "Tälern" hier hat das noch keiner der Provider wohl so richtig mitbekommen.

Mit der Networklib von PB hat wohl anscheinend jeder Probleme, seit Jahren, und da nur die "Gurus"
sich zu helfen wissen sieht der Grossteil der PB-Nutzer von aussen zu.
Ich z.B. hab es auch noch nicht geschafft, eine Server/Client - Geschichte zu basteln, die man
unbeaufsichtigt länger als 2-4h laufen lassen kann (die heftig genutzt wird in der Zeit)...
Von Hängern über Blockieren bis hin zu Abstürzen ist alles da...

Da ist grosser Nachholbedarf seitens des Teams vonnöten. Aber jeder setzt seine Prioritäten
anders. Momentan ist ja das 3D Brimborium gross am machen, was ich z.B. nicht nutze...

Das geht bei den Jungs Schritt für Schritt... Da steckt ja auch keine 500 Kopf-starke Truppe hinter.

Und anders als bei anderen Sprachen, wird hier sehr auf Crossplatform geachtet, was zwar nicht immer
geht aber es wird zumindest extremst versucht. Das kostet Zeit...
Also übe ich mich in Geduld und hoffe und warte ;)
PureBasic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom​​
Toshy
Beiträge: 713
Registriert: 22.03.2005 00:29
Computerausstattung: Computer und Strom vorhanden
Wohnort: LK Wolfenbüttel

Re: NetworkServerEvent() und #PB_NetworkEvent_File

Beitrag von Toshy »

Also an sich habe ich das bisher schon stabil hinbekommen. Na ja... bis auf hanche hänger.
Aber das lag an der unwissenheit der internne FUnktionen von PB und der Fehlerhaften Hilfedatei.
Jetzt aber langsam komme ich weiter. Ich erstelle mir das in DLL-form. auch so, daß dann wenn jeman will das nutzen kann.
aber noch brauche ich eine Weile. Ich mache das aktuell ohne Test alles im Kopf und in der IDE.
Langsam verstehe ich wie es läuft. Größtes Problem scheint aber am Server die hohe Last zu sein.
Ich lese da gerade ein Tutorial
2. Varianten zum behandeln mehrerer Clients

Es gibt eigentlich recht viele Varianten wie ein Server mehrere Clients bedienen kann:
Verwenden von select()
Für jeden Client einen eigenen Prozess starten
Für jeden Client einen eigenen Thread starten
Nicht blockierende sockets (schlechte Idee)
WSAAsyncSelect
WSAEventSelect
und weitere.. (signalgesteuerter I/O, asynchroner I/O nach Posix "Echtzeit"-Erweiterungen,..)
Und da arbeitet PB eventuell nicht optimal. Aber mal schauen.

Bis auf den Thread für eingehende Daten, der alle Clienten abfragt und der Routine die nach einem schließen eines Servers alles aufräumt habe ich das meißte als Alphaversion fertig. Nach dem ersten Test werden mir aber sicher einige schwere Fehler unter kommen. Falls nicht wäre ich genial. hehe.

Eigenartig, gerade die Netzwerk"dinge" interessieren so viele Leute. Aber die meißten kämpfen mit den Aufrufen selbst und so kommt man kaum dazu seine eigenen Proceduren zu optimieren.
1. Win10
PB6.1
Antworten