Gleicher Code, nur UDP

Für allgemeine Fragen zur Programmierung mit PureBasic.
Moxl
Beiträge: 150
Registriert: 26.10.2012 13:19

Gleicher Code, nur UDP

Beitrag von Moxl »

Guten Abend,

bin gerade dabei mich mit UDP auseinander zu setzen, also habe ich mal ein ganz einfaches Server/Client Programm gebastelt.

So, jetzt habe ich auch eine ganz einfache Frage :mrgreen:

Wieso funktioniert dieses Model, ...

Server:

Code: Alles auswählen

Procedure server(param)
  Repeat
    event=NetworkServerEvent()
    Select  event
      Case  #PB_NetworkEvent_Connect
        PrintN("Neuer Client verbunden. ID: "+Str(EventClient()))
      Case  #PB_NetworkEvent_Data
        crude$=Space(2048)
        received=ReceiveNetworkData(EventClient(), @crude$, 2048)
        newcrude$=RTrim(crude$)
        PrintN(Str(received)+" Bytes empfangen. ID: "+Str(EventClient())+" Data: "+newcrude$)
      Case  #PB_NetworkEvent_Disconnect
        PrintN("Client getrennt. ID: "+Str(EventClient()))
      Case  #PB_NetworkEvent_None
        Delay(10)
    EndSelect
  ForEver
EndProcedure

OpenConsole()
If  InitNetwork()<>0
  PrintN("Netzwerk initialisiert")
  If  CreateNetworkServer(0, 6600, #PB_Network_TCP)<>0
    PrintN("Server gestartet")
    PrintN("")
    CreateThread(@server(), param)
    Repeat
      input$=Input()
    Until input$="exit"
    End
  EndIf
EndIf
Client:

Code: Alles auswählen

Procedure client(verbindung)
  Repeat
    event=NetworkClientEvent(verbindung)
    Select  event
      Case  #PB_NetworkEvent_Data
        PrintN("Daten empfangen. Data: ")
      Case  #PB_NetworkEvent_Disconnect
        PrintN("Verbindung getrennt.")
      Case  #PB_NetworkEvent_None
        Delay(10)
    EndSelect
  ForEver
EndProcedure

OpenConsole()
If  InitNetwork()<>0
  PrintN("Netzwerk initialisiert")
  verbindung=OpenNetworkConnection("server666.no-ip.biz", 6600, #PB_Network_TCP)
  If  verbindung<>0
    PrintN("Verbindung aufgebaut")
    PrintN("")
    CreateThread(@client(), verbindung)
    Repeat
      input$=Input()
      If  input$<>""
        bytes=SendNetworkData(verbindung, @input$, Len(input$))
        PrintN(Str(bytes)+"/"+Str(Len(input$))+" Bytes gesendet.")
      EndIf
    Until input$="exit"
    End
  EndIf
EndIf
wenn man aber einfach "TCP" durch "UDP" ändert, nicht mehr?
(Bitte bei beidem den Unicode Modus ausschalten!)

Der Server zeigt noch nichtmal an, ob ein Client connected ist.
Kann mir das jemand kurz erklären? :mrgreen:

Danke schonmal im Vorraus :allright:
Benutzeravatar
man-in-black
Beiträge: 362
Registriert: 21.08.2006 17:39

Re: Gleicher Code, nur UDP

Beitrag von man-in-black »

Hi,

habs jetzt nicht getestet (und bediene mich auch eher Halbwissen), aber du musst sowohl den Server als auch den
Client als UDP starten.
Dass du keinen "Beitritt des Clients" siehst, liegt an UDP selbst. Server und Client "sprechen" sich nicht wie bei TCP ab,
sondern senden einfach auf gut Glück Datenpakete, wenn dies gefordert ist. Guck mal bei "OpenNetworkConnection" in der Hilfe.
Dort steht, dass bei UDP nur intern ein Vermerk gemacht wird, also noch kein Kontakt zum Server selbst aufgenommen wird.
Folglich kann der Server gar nicht wissen, dass er Clienten hat. ;)

MFG
MIB

P.S. Habs jetzt doch mal durchlaufen lassen. Sowohl TCP als auch UDP klappen ohne Probleme mit deinem Code. Einzig
das Erfassen der Clients vom Server wird nicht beachtet (s.o.).
(hab alles, kann alles, weiß alles!!^^)

Bild
Moxl
Beiträge: 150
Registriert: 26.10.2012 13:19

Re: Gleicher Code, nur UDP

Beitrag von Moxl »

Ja soweit ist mir das alles klar wie udp funktioniert, und das der server nicht anzeigt das ein client connected kann ich ja dann auch noch verstehen wobei ich vor 1-2 Jährchen schonmal ein udp model gemacht habe und es dort funktioniert hat.
Was ich aber nicht verstehe ist, dass wenn man jetzt daten sendet, nichts ankommt. Auch wenn man 100 mal was sendet...
Hat das bei dir funktioniert?
Benutzeravatar
man-in-black
Beiträge: 362
Registriert: 21.08.2006 17:39

Re: Gleicher Code, nur UDP

Beitrag von man-in-black »

P.S. Habs jetzt doch mal durchlaufen lassen. Sowohl TCP als auch UDP klappen ohne Probleme mit deinem Code.
Ich musste nur die Serveradresse auf den Localhost umschreiben, damit ichs überhaupt testen konnte.
server666.no-ip.biz
Wie hast du denn deinen Server aufgesetzt? Die Verbindung scheint ja nicht nur über deinen PC sondern übers Netz zu laufen?
Hohe Datenverlustrate bis zum Ziel? Mag ein Zwischenknoten deine Anfrage oder dich nicht? ;)
(Sind nur spontane Ideen auf Basis von Halbwissen)
(hab alles, kann alles, weiß alles!!^^)

Bild
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8820
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: Gleicher Code, nur UDP

Beitrag von NicTheQuick »

Falls du über einen Router gehst, musst du natürlich den Port für TCP und für UDP freischalten und nicht nur für eins von beiden.
Moxl
Beiträge: 150
Registriert: 26.10.2012 13:19

Re: Gleicher Code, nur UDP

Beitrag von Moxl »

Ahh :praise:

es liegt wahrscheinlich an der portfreigabe... wie schon angenommen lass ich den server ja durch den router laufen,
wenn ich localhost eingebe funktioniert alles. :allright:

Jetzt stört mich nur noch das der Server nicht erkennt wenn ein Client connected.
Da muss ich mir wohl was überlegen wie der Server es checkt. :mrgreen:

Danke für die Antworten :allright:

EDIT: Jop, musste UDP beim Router freigeben. Jetzt funktionierts :allright: Danke :praise:
Benutzeravatar
grapy
Beiträge: 108
Registriert: 09.09.2004 09:05

Re: Gleicher Code, nur UDP

Beitrag von grapy »

siehe auch: https://de.wikipedia.org/wiki/User_Datagram_Protocol

UDP ist ein verbindungsloses, nicht-zuverlässiges und ungesichertes wie auch ungeschütztes Übertragungsprotokoll.
Das bedeutet, es gibt keine Garantie, dass ein einmal gesendetes Paket auch ankommt, dass Pakete in der gleichen Reihenfolge ankommen,
in der sie gesendet wurden, oder dass ein Paket nur einmal beim Empfänger eintrifft.

Daher gibt es auch keinen Connect vom Client. Dieser feuert nur Pakete ins Netzwerk. Die kommen eben an oder nicht.
Moxl
Beiträge: 150
Registriert: 26.10.2012 13:19

Re: Gleicher Code, nur UDP

Beitrag von Moxl »

Hallo,

jetzt habe ich die Codes mal so umgeschrieben, dass ein Bild gesendet wird.
Allerdings habe ich jetzt wieder das selbe Problem wie am anfang... mit TCP klappt alles und mit UDP sendet er erst gar nichts :|

woran liegt das?

Server:

Code: Alles auswählen

UseJPEGImageEncoder()
UseJPEGImageDecoder()

If  OpenWindow(0, 0, 0, 500, 500, "Bild")
  ImageGadget(0, 0, 0, 500, 500, 0)
EndIf
OpenConsole("Server")
If  InitNetwork()<>0
  PrintN("Netzwerk initialisiert")
  If  CreateNetworkServer(0, 6600, #PB_Network_TCP)<>0
    PrintN("Server gestartet")
    PrintN("")
    Repeat
      Delay(10)
      event=NetworkServerEvent()
      Select  event
        Case  #PB_NetworkEvent_Connect
          clientid=EventClient()
        Case  #PB_NetworkEvent_Data
          Debug "daten empfangsbereit"
          clientid=EventClient()
          size=0
          sizereceived=ReceiveNetworkData(clientid, @size, 4)
          If  size=1
            clientid=EventClient()
            PrintN("Neuer Client verbunden. ID: "+Str(clientid))
          Else
            PrintN(Str(sizereceived)+" Bytes empfangen. ID: "+Str(clientid)+" Data: "+Str(size))
            *daten=AllocateMemory(size)
            errorcounter=0 
            ReceivedBytes=0
            Repeat
              result=ReceiveNetworkData(clientid, *daten+ReceivedBytes, size-ReceivedBytes)
              If result=-1
                Delay(1)
                errorcounter+1
              Else
                ReceivedBytes+result
                errorcounter=0
              EndIf
            Until ReceivedBytes=size Or errorcounter > 5000
            PrintN(Str(ReceivedBytes)+" Bytes empfangen. ID: "+Str(clientid))
            If  ReceivedBytes=size
              If  CatchImage(0, *daten)
                SetGadgetState(0, ImageID(0))
              EndIf
              FreeMemory(*daten)
            EndIf
          EndIf
        Case  #PB_NetworkEvent_Disconnect
          clientid=EventClient()
          PrintN("Client getrennt. ID: "+Str(clientid))
        Case  #PB_NetworkEvent_None
          Delay(10)
      EndSelect
      event=WindowEvent()
    Until event=#PB_Event_CloseWindow
    End
  EndIf
EndIf
Client:

Code: Alles auswählen

UseJPEGImageEncoder()
UseJPEGImageDecoder()

OpenConsole("Client")
If  InitNetwork()<>0
  PrintN("Netzwerk initialisiert")
  verbindung=OpenNetworkConnection("localhost", 6600, #PB_Network_TCP)
  If  verbindung<>0
    PrintN("Verbindung aufgebaut")
    PrintN("")
    hello=1
    SendNetworkData(verbindung, @hello, 4)
    Repeat
      input$=Input()
      If  input$<>""
        If  LoadImage(0, "") ;<----- IRGEND EIN BILD EINFÜGEN
          *bild=EncodeImage(0, #PB_ImagePlugin_JPEG)
          *daten=AllocateMemory(4+MemorySize(*bild))
          PokeL(*daten, MemorySize(*bild))
          MoveMemory(*bild, *daten+4, MemorySize(*bild))
          errorcounter=0
          sendbytes=0
          Repeat
            result=SendNetworkData(verbindung, *daten+sendbytes, MemorySize(*daten)-sendbytes)
            If  result=-1 Or result=0
              Delay(1)
              errorcounter+1
            Else
              errorcounter=0
              sendbytes+result
            EndIf
          Until sendbytes=MemorySize(*daten) Or errorcounter>5000
          PrintN(Str(sendbytes)+"/"+Str(MemorySize(*daten))+" Bytes gesendet.")
          FreeMemory(*bild)
          FreeMemory(*daten)
          FreeImage(0)
        EndIf
      EndIf
    Until input$="exit"
    End
  EndIf
EndIf
(Beim Client müsst ihr den Pfad von dem Bild angeben.)


Hoffe Ihr könnt mir wiedermal helfen :allright:
Benutzeravatar
HeX0R
Beiträge: 3056
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win11 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2 + 3
Kontaktdaten:

Re: Gleicher Code, nur UDP

Beitrag von HeX0R »

Du kannst nicht so einfach ein Bild per UDP versenden.
UDP nimmt man dann, wenn man Dinge überträgt, bei denen es egal ist, ob Pakete mal verloren gehen, wie z.B. Video oder Audio Streams.

Wenn Deinem Bild aber ein Paket fehlt, oder die Reihenfolge falsch ist (beides bei UDP möglich), lässt sich das gar nicht mehr darstellen.

Da musst Du schon etwas mehr Gehirnschmalz einsetzen, z.b. die einzelnen Pakete markieren und dann beim Empfänger schauen, ob alle da sind und auch in der richtigen Reihenfolge.
Dann hast Du aber schon wieder einen Handshake, der den Vorteil von UDP nahezu zunichte macht.
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7035
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Gleicher Code, nur UDP

Beitrag von STARGÅTE »

Bei mir funktioniert dein Code nicht mal mit TCP.
"IRGEND EIN BILD EINFÜGEN" scheint nicht zu klappen.

Wie schon zuvor geschrieben wurde, sind das zwei völlig verschiedene Protokolle (mit unterschiedlichen Anwendungsgebieten).

Da du nun zwei mal SendNetworkData() in deinem Code hast:

Code: Alles auswählen

SendNetworkData(verbindung, @hello, 4)
SendNetworkData(verbindung, *daten+sendbytes, MemorySize(*daten)-sendbytes)
Unter UDP kann es nun sein, dass zuerst dein Bild ankommt und dann erst dein @hello

Lass dir doch mal ein bisschen mehr Debuggen, z.B. das resultat von SendNetworkData() oder ReceiveNetworkData()

Edit: Ah ich muss bei Input etwas reinschreiben.

Ich bekomme bei SendNetworkData() immer -1, vermutlich weil die Puffergröße die von UDP überschreitet
Anmerkungen
Bei UDP-Verbindungen beträgt die maximale 'Länge' 2048. Bei TCP-Verbindungen beträgt die maximale 'Länge' 65536.
Du musst dein Bild also vermutlich in "Häpchen" senden.
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
Antworten