Seite 1 von 1

Disconnect(event) am Clienten

Verfasst: 15.05.2012 12:31
von Toshy
Hallo Leute.

Bisher verwende ich noch keine "Eventabfrage" beim Clienten.
An Links sind mir folgende Beitrage dazu bekannt:
http://www.purebasic.fr/english/viewtop ... 12&t=42559
und
http://www.purebasic.fr/german/viewtopi ... ientEvent4
als wichtigste und an sonsten noch ein paar weitere die aber meißt um die selben Codes gehen.
Mein "Englischproblem" hat ja schon der eine oder andere mitbekommen.
Bevor ich aber einen Code bei mir einbaue, möchte ich schon wenigstens in Grundzügen verstehen was der Code macht. Daher möchte ich zum Thema "Disconnect" beim Clienten doch Einiges nachfragen und erklärt bekommen.

1. Gibt es "systemseitig" (also z.B. vom TCP/IP-Protokoll) einen Disconnect Event so wie beim Server?
2. Falls ja, weiß jemand warum es das nicht in PB gibt?
3. Abhängig von den Antworten für Frage 1. und 2. , also wenn es keine "systemseitiges" Event gibt, was für ein "Event" fragt dann der Code aus dem Link von Dark(Player) und purefan ab. An dieser Stelle nur ganz grob. Sieht nach irgend einem überprüfen nach einem Fehler auf.
4. Wenn ich die Networklib in PB nutze und beim Clienten eine Verbindung unterbrochen wird (Disconnect, Verbindungsabbruch... Serverfehler), was passiert dann bei Clienten "intern"? Wie lange ich die PB-ID noch gültig? Ist sie gleich ungültig oder die ID so lange noch gültig und vergeben, bis ich ein Disconnect (auf die "tote" Verbindung "lege"? Oder was genau geschieht da. Nicht das die ID dann automatisch ohne Event frei wird und wieder neu vergeben wird.

Weiterhin möchte ich den Code selbst überschauen, auch wegen threadsicherheit usw. Da gibt es irgend im Forum eine angepaßt Include (ich glaube von Alex; nachtrag: gefundenhttp://www.purebasic.fr/german/viewtopi ... lient+alex), aber ich will da wenigstens ein wenig von verstehen. Dazu werde ich den super gut strukturierten Aufbau der Vorlage anders umbauen (mehr Ifabfragen usw.). Dies Stück für Stück und hier dann nachfragen welcher Teil was macht.
Das werde ich hier unter diesem Thema machen, aber erst wenn ich obiges wenigstens teilweise beantwortet bekommen habe.

5. Vorab würde ich zu dark's bzw. alex Code aber schon mal wissen, was es mit dem "UDP-Teil" auf sich hat. Im Thema von darkplayer wird von Usern UDP angesprochen aber meine Übersetzfähigkeit ist ja sehr begrenzt. Im Code von alex steht gleich zu Anfang etwas über UDP, allerdings als ComilerIF. Bedeutet dies, ich muß mich vor dem Compelieren entscheiden, ob ich TCP oder UPD nutzen will und?

Gruß
Toshy

Re: Disconnect(event) am Clienten

Verfasst: 16.05.2012 02:33
von Dark
Hallo,

da der von dir erwähnte Code von PureFan und mir geschrieben wurde sage ich mal etwas dazu:

1. Es gibt zwei Möglichkeiten wie ein Disconnect im System ausgelöst werden kann:
- das Gegenüber sendet ein TCP Packet wo das Reset Flag gesetzt ist
- man sendet Daten und bekommt trotz erneuten Sendens innerhalb eines gewissen Timeouts keine Bestätigung, das die Daten angekommen sind.

2. Das ist eine gute Frage, es gibt keinen offensichtlichen Grund warum es nicht eingebaut wurde.

3. Das Disconnect Event kann recht einfach im System festgestellt werden, es wird das gleiche "Event" zurückgegeben als ob Daten empfangen wurden. Der Unterschied ist aber, dass keine Daten vorhanden sind. Es wird dazu kein Fehler abgefragt, sondern nur überprüft ob das System einen Fehler bei einem der Befehle zurückgibt. Dies deutet auch darauf hin, dass das Socket nicht mehr gültig ist und somit die Verbindung tot ist.

4. Wie lange die Purebasic ID gültig ist kann ich dir nicht genau sagen, aber ich würde einfach nach einem Disconnect CloseConnection() aufrufen, damit müsste Purebasic auf jeden Fall die ID wieder freigeben. Es macht ja auch keinen Sinn mehr die ID von einer toten Verbindung zu speichern.

Zu dem Code von Alex kann ich jetzt nichts sagen, mit dem habe ich mich noch nicht beschäftigt.

5. UDP kennt keine Zustände. Man sendet einfach Daten und ob die jemals ankommen ist Unbekannt. Daher macht mein Code in diesem Zusammenhang keinen Sinn. In diesem Fall gibt mein Code immer ein Disconnect Event zurück. Wenn man nur UDP Verbindungen nutzt sollte man meine Include einfach nicht verwenden, da sie keinen Vorteil bringt. Nur wenn man beides benutzt, kann es zu diesem Problem kommen und man kann entweder einfach das Disconnect Event bei UDP Verbindungen ignorieren oder den Workaround benutzen den ich noch als Antwort dazu geschrieben hatte.

Zu Alex Codes kann ich nichts sagen.

Dark

Re: Disconnect(event) am Clienten

Verfasst: 16.05.2012 13:46
von Toshy
Danke.

Noch mal zu Punkt 3.
Deine Erklärung ist klar und deutliche. Wenn ich also recht verstehe wird dieses "Disconnect-Event" am Clienten dann wohl "sofort" ausgelöst wenn die Gegenstelle (also der Server) dieses "Resetflag" sendet. Wenn dies nicht geschieht (Verbindung aus anderen Gründen unterbrochen wird) bekommt man das "Disconnect-Event" also erst, sobald man selbst versucht auf diese Verbindung durch senden zuzugreifen. Richtig? Eventuell wohl auch, wenn man auf ander Art direkt auf den Socket zu greift?

Zu 4.
Ich hoffe in meinem Thema "zur Zukunft der Networklib und IPv6" kann dann auch dies geklärt werden. Denn es wäre ja fatal, wenn ich im Programm als Client nicht mitbekommen würde, das PB die ID und Socket wieder frei gibt. Dann könnte es nicht nur passieren das ich auf die ungültigen Daten zugreife, sondern das die IP und Socket ja wieder neu vergeben wird und wenn das geschieht bevor ich auf die Verbindung erneut zu greife, dann wäre die Verbindung(sid) ja wieder gültig. und ich könnte versehentlich an wen anders Daten senden. Aber da hoffe ich erst mal, das wenigstens dies verhindert wird.

(neuer Punkt:) 5.
Dein Code ist natürlich die beste Möglichkeit das Disconnect abzufangen. An sich aber könnte man (so hatte ich das damals gemacht) in der eigenen IDVerwaltung einfach einen Zähler je Verbindung einbauen. Einen Zähler der erhöht wird, wenn Daten nicht versendet werden. Sind nach einer bestimmten Anzahl an Sendungswiederholungen (z.B. 3 Stück innerhalb von einer Minute) der selben Daten immer noch erfolglos, kann man davon ausgehen, das die Verbindung nicht mehr besteht und "selbst disconnecten". Nicht so schön wie bei dir, aber bis auf das "Resetflag" vom Server wohl im Ergebnis das selbe!???

(neuer Punkt:) 6.
Das UDP irgendwie "Verbindungslos" ist, habe ich schon oft gelesen. Was ich nur nicht verstehe, wozu es dann ein OpenNetworkConnection gibt? Dort wird doch eine Verbindung hergestellt und ich kann dort Daten so lange auf dieser ID senden, bis ich disconnecte. Was läuft da wirklich ab? Ist das nur so eine Art "Virtuelle Verbindung" die an sich nur für mich PB-Programmierer besteht und in wirklichkeit je Übertragung neu aufgebaut wird? Oder wie sonst?

(neuer Punkt:) 7.
Wenn ich also TCP und UDP nutze (ich erstelle nur endliche für mich einen eigenen Networkmanager, damit es für mich einfacher wird), muß ich nur dafür sorge tragen, das dein Code nur bei den TCP-Verbindungen genutzt wird, richtig? Ist ja kein Problem, in meiner IDstruktur steht eh drinn, was für ein Server- bzw. Clientverbindungsmodus gewählt wurde.
In kombination zu 6. stellt sich hier dann natürlich die Frage, wie man mit UDP-"Verbindungen" und "Disconnects umgeht. Es dürfte dann ja auch am Server keine Disconnects geben, wenn man UDP(-Server) verwendet. Ich verstehe diesen bei UDP noch nicht wirklich, wie es "Verbindungslos" ist, wenn in PB aber irgendwie doch Verbindungen existieren. Da habe ich jetzt noch gar keinen Durchblick.

(neuer Punkt:) 8.
So, ich erstelle den bei mir zum verständniss neu, auch "nicht so übersichtliche Art", aber hauptsache ich kapiere das auf meine Art. Das poste ich aber nicht im Einzelnen, erst wenn ich es zusammen habe oder eine Frage dazu. Ich schreibe jetzt einfach mal in deinem Code mitten rein, was ich erkenne und was nicht. Erst einmal aber nur die Windowsvariante, Linux mache ich danach.

Code: Alles auswählen

CompilerIf #PB_Compiler_OS = #PB_OS_Windows ;{
  ; #FIONREAD is already defined [b]--> Konstante die in PB/Windows schon definiert ist[/b]
  ; FD_SET is already defined [b]--> Struktur die in PB/Windows schon definiert ist[/b]
 
  Macro FD_ZERO(set) [b]--> biete nur eine schöne Art eine Struktur des Aufbaus "fd_set" im Feld "fd_count" auf NULL zu setzten[/b]
    set\fd_count = 0
  EndMacro
 
  Procedure.i FD_SET(fd.i, *set.FD_SET) [b]--> schreibt in die Struktur mit Aufbau FD_SET in ein Arrayfeld das/ein Socket(Verbindung) und zählt den Counter für das Arrayfeld hoch[/b]
    If *set\fd_count < #FD_SETSIZE
      *set\fd_array[ *set\fd_count ] = fd
      *set\fd_count + 1
    EndIf
  EndProcedure
 
  Procedure.i FD_ISSET(fd.i, *set.FD_SET)
    Protected I.i
    For I = *set\fd_count - 1 To 0 Step -1
      If *set\fd_array[I] = fd
        ProcedureReturn #True
      EndIf
    Next
   
    ProcedureReturn #False
  EndProcedure
 
  Procedure.i _NFDS(*set.FD_SET)
    ProcedureReturn *set\fd_count
  EndProcedure
  ;}
CompilerEndIf
 
 
CompilerIf Defined(TIMEVAL, #PB_Structure) = #False ;{
  Structure TIMEVAL
    tv_sec.l
    tv_usec.l
  EndStructure ;}
CompilerEndIf

Procedure.i Hook_NetworkClientEvent(Connection.i)
  Protected Event.i = NetworkClientEvent(Connection)
  If Event
    ProcedureReturn Event
  EndIf
 
  Protected hSocket.i = ConnectionID(Connection)
  Protected tv.timeval, readfds.fd_set, RetVal.i, Length.i
  tv\tv_sec  = 0 ; Dont even wait, just query status
  tv\tv_usec = 0
 
  FD_ZERO(readfds)
  FD_SET(hSocket, readfds)
 
  ; Check if there is something new
  RetVal = select_(_NFDS(readfds), @readfds, #Null, #Null, @tv)
  If RetVal < 0 ; Seems to be an error
    ProcedureReturn #PB_NetworkEvent_Disconnect
  ElseIf RetVal = 0 Or Not FD_ISSET(hSocket, readfds) ; No data available
    ProcedureReturn 0
  EndIf
 
  ; Check if data is available?
  CompilerIf #PB_Compiler_OS = #PB_OS_Windows
    RetVal = ioctlsocket_(hSocket, #FIONREAD, @Length)
  CompilerElse
    RetVal = ioctl_(hSocket, #FIONREAD, @Length)
  CompilerEndIf
  If RetVal Or Length = 0 ; Not successful to query for data available OR no data available ? This seems to be an error!
    ProcedureReturn #PB_NetworkEvent_Disconnect
  EndIf
 
  ProcedureReturn 0
EndProcedure

Macro NetworkClientEvent(Connection)
  Hook_NetworkClientEvent(Connection)
EndMacro
den Sinn von "CompilerIf Defined" habe ich nie so ganz kapiert. Du scheinst mit "CompilerIf Defined(TIMEVAL, #PB_Structure) = #False ;{" zu überprüfen ob die Struktur bereits bekannt ist und wenn nicht erstellst du sie. Nur weiß man das nicht vorher? Bei den anderen weißt du ja auch das sie in Windows vorhanden und in Linux nicht vorhanden sind.

(neuer Punkt:) 8.
was bedeutet

Code: Alles auswählen

  tv\tv_sec  = 0 ; Dont even wait, just query status
  tv\tv_usec = 0
genau? Sind änderungen am Wert sinnvoll und was bewirken sie? Eine Art "Timeout" bzw. wartezeit bis "etwas" als Fehler angesehen wird????

(neuer Punkt:) 9.
Procedure.i FD_SET
es wird immer nur hoch gezählt, wenn man einen Server hat, der lange läuft und bei dem die Verbindungen oft auf und abgebaut wird, dann wird das Array doch immer größer und wäre dann theoretisch irgend wann voll. oder wie? #FD_SETSIZE gibt bei mir als Wert 64 aus. Dem entsprechend würden nur in die Struktur nur bis zu 64 Verbindungssocket eingefügt werden.
Wenn ich das aber richtig sehe ist readfds.fd_set durch protect ja nur in der Procedur bekannt und wird bei jedem Aufruf neu gesetzt. Worüber ich mir noch nie Gedanken gemacht hatte ist, da es sich ier ja um einen Speicherbereich handelt, müßte doch auch die Struktur wieder zurück gesetzt sein, oder? Bleiben die Werte nun bestehen (ups.. dann häte ich hier einen dummen fehler bei mir begangen) oder bedeutet "zurückgesetzt" (steht so in der Hilfe) nicht auch, das der Inhalt der strukturierten Variable "leer" ist. dann würe fd_count beim Aufruf von FD_SET() immer NULL und danach immer EINS. Falls ich protected aber total mißverstanden habe, dann wiederum würde fd_count ja nach 64 Verbindungsaufbaus bereits nicht mehr funktionieren.

(neuer Punkt:) 10.
Treadsicherheit. Wenn ich mehrere Threads bei eingehenden und ausgehenden Verbindungen habe muß ich ja auch die Treadsicherheit achten.
Dazu reicht es auf ausgehender Seite ja wohl, wenn ich innerhalb der Procedure Hook_NetworkClientEvent(Connection.i) einfach ein Mutex nutze.
Kann es mit den PB-Funktionen auf der Serverseite probleme geben?
Oder ist es vielleicht gar nicht notwendig hier ein Mutex zu verwenden?
(In Bezug auf deinen code und die Funktionen, das ich meine Abfragen schützen muß ist klar.)

So, daß sind zwar wohl noch nicht alle Dinge, aber ein Anfang um es etwas mehr zu verstehen.

Herzlichen Dank.

Re: Disconnect(event) am Clienten

Verfasst: 16.05.2012 21:58
von Dark
3) Wenn die Verbindung abbricht und das Gegenüber vorher kein Reset Paket gesendet hat, bemerkt man den Disconnect erst, wenn man selber Daten sendet.

4) Ich denke das zumindestens das PB Handle gültig bleibt, ob PB das Socket Handle schließt weiss ich nicht. Ich würde bei einem Disconnect einfach CloseConnection() aufrufen und dann kannst du dir 100% sicher sein das alles freigegeben wird.

5) Diese Methode würde in der Theorie zwar funktionieren, aber in der Praxis würde ich davon abraten. Das TCP Protokoll ist recht komplex und es ist nicht auszuschließen, das eine kurze Zeit das Senden fehlschlägt obwohl die Verbindung noch intakt ist. Da einem das System die ganze Arbeit abnimmt sollte man dies auch nutzen.

6) PB hat das nur als Anlehnung an TCP so eingebaut und teilweise auch einige Funktionalitäten von UDP damit entfernt. (Stichwort P2P). Es gibt bei UDP keine Verbindungen und auch keine Unterscheidung zwischen Client oder Server. Die APIs erlauben es einfach ein UDP socket zu erstellen und damit Daten an jede beliebige IP zu senden. Der Unterschied zwischen Client und Server ist nur der, das man beim Server einen fest Port auswählt und beim Client sich einen Port zuweisen lässt.

7) Man muss sich selbst ein Protokoll bauen welches, ähnlich wie TCP, Daten erneut sendet und Disconnects erkennt. So in der Art wie du in Punkt 5 vorgeschlagen hast. Die Verwendung von UDP macht auch nur dann Sinn, wenn es gewollt ist, das Daten verloren gehen. Ein Beispiel hierfür wäre eine Videokonferenz. Hier möchte man nicht das ein Bild 3 mal erneut gesendet wird und die Verzögerung immer größer wird. Besser ist es, wenn mal ein Bild verloren geht und dafür das ganze einigermaßen Live ist.

8) PureBasic meldet einen Fehler wenn eine Struktur doppelt deklariert wird. Die TIMEVAL Struktur ist in manchen Betriebssystemen schon durch PB vordefiniert und es würde vom Compiler eine Fehlermeldung angezeigt, wenn man versucht diese doppelt zu deklarieren. Desweiteren ist diese Struktur unter Linux/MacOS nicht gerade unüblich und es wäre möglich das jemand diese Struktur schon im Code definiert hat. Um diese Fehler zu verhindern, wird die Struktur nur deklariert wenn sie vorher nicht schon deklariert wurde.

Das mit dem Timeout heißt nur, das er nicht wartet bis Netzwerkdaten vorhanden sind sondern sofort zurück kehrt. Das ist das selbe wie WindowEvent und WaitWindowEvent.

9)
Bei dem Aufruf der Funktion sind immer alle lokalen Werte mit 0 initialisiert. In diesem Fall befindet sich tatsächlich nur ein einziges Socket in dem Array. Die API unterstützt aber eigentlich wesentlich mehr Sockets in dem select Befehl, unter Windows bis zu 64. Der Grund warum ich da ganze trotzdem so kompliziert mache ist, weil dies die dokumentierte Vorgehensweise von der Windows/Linux/MacOS API ist. In C++ sind so Befehle wie FD_ISSET als Macro vordefiniert, damit sein Source Code unter Linux/MacOS/Windows ohne Änderungen compiliert. Intern arbeiten diese aber teilweise anders und da PureBasic nicht in allen Betriebssystem eine Deklaration mitliefert habe ich diese 1:1 aus den C++ Dateien übersetzt.

10)
Meine API Aufrufe sind auf jeden Fall threadsicher, in wie weit dies aber für die von mir verwendeten PB Befehle NetworkClientEvent und ConnectionID gilt, kann ich nicht sagen.

Re: Disconnect(event) am Clienten

Verfasst: 08.06.2012 08:57
von Linus05
Dark hat geschrieben:3) Wenn die Verbindung abbricht und das Gegenüber vorher kein Reset Paket gesendet hat, bemerkt man den Disconnect erst, wenn man selber Daten sendet.

4) Ich denke das zumindestens das PB Handle gültig bleibt, ob PB das Socket Handle schließt weiss ich nicht. Ich würde bei einem Disconnect einfach CloseConnection() aufrufen und dann kannst du dir 100% sicher sein das alles freigegeben wird.

5) Diese Methode würde in der Theorie zwar funktionieren, aber in der Praxis würde ich davon abraten. Das TCP Protokoll ist recht komplex und es ist nicht auszuschließen, das eine kurze Zeit das Senden fehlschlägt obwohl die Verbindung noch intakt ist. Da einem das System die ganze Arbeit abnimmt sollte man dies auch nutzen.

6) PB hat das nur als Anlehnung an TCP so eingebaut und teilweise auch einige Funktionalitäten von UDP damit entfernt. (Stichwort P2P). Es gibt bei UDP keine Verbindungen und auch keine Unterscheidung zwischen Client oder Server. Die APIs erlauben es einfach ein UDP socket zu erstellen und damit Daten an jede beliebige IP zu senden. Der Unterschied zwischen Client und Server ist nur der, das man beim Server einen fest Port auswählt und beim Client sich einen Port zuweisen lässt.

7) Man muss sich selbst ein Protokoll bauen welches, ähnlich wie TCP, Daten erneut sendet und Disconnects erkennt. So in der Art wie du in Punkt 5 vorgeschlagen hast. Die Verwendung von UDP macht auch nur dann Sinn, wenn es gewollt ist, das Daten verloren gehen. Ein Beispiel hierfür wäre eine Videokonferenz. Hier möchte man nicht das ein Bild 3 mal erneut gesendet wird und die Verzögerung immer größer wird. Besser ist es, wenn mal ein Bild verloren geht und dafür das ganze einigermaßen Live ist.

8) PureBasic meldet einen Fehler wenn eine Struktur doppelt deklariert wird. Die TIMEVAL Struktur ist in manchen Betriebssystemen schon durch PB vordefiniert und es würde vom Compiler eine Fehlermeldung angezeigt, wenn man versucht diese doppelt zu deklarieren. Desweiteren ist diese Struktur unter Linux/MacOS nicht gerade unüblich und es wäre möglich das jemand diese Struktur schon im Code definiert hat. Um diese Fehler zu verhindern, wird die Struktur nur deklariert wenn sie vorher nicht schon deklariert wurde.

Das mit dem Timeout heißt nur, das er nicht wartet bis Netzwerkdaten vorhanden sind sondern sofort zurück kehrt. Das ist das selbe wie WindowEvent und WaitWindowEvent.

9)
Bei dem Aufruf der Funktion sind immer alle lokalen Werte mit 0 initialisiert. In diesem Fall befindet sich tatsächlich nur ein einziges Socket in dem Array. Die API unterstützt aber eigentlich wesentlich mehr Sockets in dem select Befehl, unter Windows bis zu 64. Der Grund warum ich da ganze trotzdem so kompliziert mache ist, weil dies die dokumentierte Vorgehensweise von der Windows/Linux/MacOS API ist. In C++ sind so Befehle wie FD_ISSET als Macro vordefiniert, damit sein Source Code unter Linux/MacOS/Windows ohne Änderungen compiliert. Intern arbeiten diese aber teilweise anders und da PureBasic nicht in allen Betriebssystem eine Deklaration mitliefert habe ich diese 1:1 aus den C++ Dateien übersetzt.

10)
Meine API Aufrufe sind auf jeden Fall threadsicher, in wie weit dies aber für die von mir verwendeten PB Befehle NetworkClientEvent und ConnectionID gilt, kann ich nicht sagen.


Hi, ich verstehe Punkt 5 nicht ganz recht "Diese Methode würde in der Theorie zwar funktionieren, aber in der Praxis würde ich davon abraten. Das TCP Protokoll ist recht komplex und es ist nicht auszuschließen, das eine kurze Zeit das Senden fehlschlägt obwohl die Verbindung noch intakt ist. Da einem das System die ganze Arbeit abnimmt sollte man dies auch nutzen."

Ist das TCP-Protokoll zwingend notwendig?

Re: Disconnect(event) am Clienten

Verfasst: 08.06.2012 09:24
von Toshy
Erst mal Danke an Dark. Ich wollte nur nicht nur für ein Danke eine Antwort schreiben. Erst wenn ich da noch nachfragen habe. Und die kommen sicher noch.

@Linus05:
Die ganze Network Lib beruht auf dem TCP-Protokoll(UPD ist natürlich auch noch da). Die Website hier die du gerade liest kannst du nur lesen weil dein Rechner das TCP-Protokoll nutzt. TCP wird automatisch genutzt, das macht das Betriebssystem. Davon bekommst du an sich ni chts mit.
Mir ging es unter anderem unter Punkt 5 nur darum, das halt die "Disconnectmeldung" vom Betriebssystem von Purebasic am Clienten einfach nicht weiter gegeben wird. Irgendwie muß man das Disconnect aber mal mitbekommen. Die Hilfsmaßnahem von mir habe ich aber gleich nach der Vorlage von Dark rausgeschmissen. Und die Vorlage jetzt doch so gelassen. Grob habe ich sie kapiert, aber mir nicht die einzelnen Strukturen und Apiaufrufe angeschaut.

Einzige weil PB in der Networklib einige Dinge nicht weitergibt und Einiges entgegen der Hilfebeschreibung anders abläuft muß man dann notfalls versuchen zu basteln. Wenn es aber einen Code gibt, der im Grunde nur "das vergessene Auswerten der Rückmeldungen" nachträglich einbaut, dann sollte man das nutzen. ich wollte nur wissen, ob man es auch so machen könnte. Denn ich hatte bis daher noch nicht kapiert, das der Code macht. Ebenso muß man beim Dateiempfang und senden noch ein wenig nachbessern, sonst kann das Programm hängen.

Noch mal kurz zusammen gefaßt:
Das TCP-Protokoll wird automatsich durch Windows und PB genutzt und du mußt dich darum nicht kümmern.

Re: Disconnect(event) am Clienten

Verfasst: 07.09.2012 13:51
von Linus
Linus05 hat geschrieben:
Dark hat geschrieben:3) Wenn die Verbindung abbricht und das Gegenüber vorher kein Reset Paket gesendet hat, bemerkt man den Disconnect erst, wenn man selber Daten sendet.

4) Ich denke das zumindestens das PB Handle gültig bleibt, ob PB das Socket Handle schließt weiss ich nicht. Ich würde bei einem Disconnect einfach CloseConnection() aufrufen und dann kannst du dir 100% sicher sein das alles freigegeben wird.

5) Diese Methode würde in der Theorie zwar funktionieren, aber in der Praxis würde ich davon abraten. Das TCP Protokoll ist recht komplex und es ist nicht auszuschließen, das eine kurze Zeit das Senden fehlschlägt obwohl die Verbindung noch intakt ist. Da einem das System die ganze Arbeit abnimmt sollte man dies auch nutzen.

6) PB hat das nur als Anlehnung an TCP so eingebaut und teilweise auch einige Funktionalitäten von UDP damit entfernt. (Stichwort P2P). Es gibt bei UDP keine Verbindungen und auch keine Unterscheidung zwischen Client oder Server. Die APIs erlauben es einfach ein UDP socket zu erstellen und damit Daten an jede beliebige IP zu senden. Der Unterschied zwischen Client und Server ist nur der, das man beim Server einen fest Port auswählt und beim Client sich einen Port zuweisen lässt.

7) Man muss sich selbst ein Protokoll bauen welches, ähnlich wie TCP, Daten erneut sendet und Disconnects erkennt. So in der Art wie du in Punkt 5 vorgeschlagen hast. Die Verwendung von UDP macht auch nur dann Sinn, wenn es gewollt ist, das Daten verloren gehen. Ein Beispiel hierfür wäre eine Videokonferenz. Hier möchte man nicht das ein Bild 3 mal erneut gesendet wird und die Verzögerung immer größer wird. Besser ist es, wenn mal ein Bild verloren geht und dafür das ganze einigermaßen Live ist.

8) PureBasic meldet einen Fehler wenn eine Struktur doppelt deklariert wird. Die TIMEVAL Struktur ist in manchen Betriebssystemen schon durch PB vordefiniert und es würde vom Compiler eine Fehlermeldung angezeigt, wenn man versucht diese doppelt zu deklarieren. Desweiteren ist diese Struktur unter Linux/MacOS nicht gerade unüblich und es wäre möglich das jemand diese Struktur schon im Code definiert hat. Um diese Fehler zu verhindern, wird die Struktur nur deklariert wenn sie vorher nicht schon deklariert wurde.

Das mit dem Timeout heißt nur, das er nicht wartet bis Netzwerkdaten vorhanden sind sondern sofort zurück kehrt. Das ist das selbe wie WindowEvent und WaitWindowEvent.

9)
Bei dem Aufruf der Funktion sind immer alle lokalen Werte mit 0 initialisiert. In diesem Fall befindet sich tatsächlich nur ein einziges Socket in dem Array. Die API unterstützt aber eigentlich wesentlich mehr Sockets in dem select Befehl, unter Windows bis zu 64. Der Grund warum ich da ganze trotzdem so kompliziert mache ist, weil dies die dokumentierte Vorgehensweise von der Windows/Linux/MacOS API ist. In C++ sind so Befehle wie FD_ISSET als Macro vordefiniert, damit sein Source Code unter Linux/MacOS/Windows ohne Änderungen compiliert. Intern arbeiten diese aber teilweise anders und da PureBasic nicht in allen Betriebssystem eine Deklaration mitliefert habe ich diese 1:1 aus den C++ Dateien übersetzt.

10)
Meine API Aufrufe sind auf jeden Fall threadsicher, in wie weit dies aber für die von mir verwendeten PB Befehle NetworkClientEvent und ConnectionID gilt, kann ich nicht sagen.


Hi, ich verstehe Punkt 5 nicht ganz recht "Diese Methode würde in der Theorie zwar funktionieren, aber in der Praxis würde ich davon abraten. Das TCP Protokoll ist recht komplex und es ist nicht auszuschließen, das eine kurze Zeit das Senden fehlschlägt obwohl die Verbindung noch intakt ist. Da einem das System die ganze Arbeit abnimmt sollte man dies auch nutzen."

Ist das TCP-Protokoll zwingend notwendig?


Ohne TCP-Protokoll gehts erst gar nicht :wink: