Seite 1 von 3

UDP Server empfängt nichts vom UDP Client

Verfasst: 12.12.2004 15:57
von MVXA
Hallo !
Ich hab leider Probleme mit dem Windows netzwerk und wollt mir ein Tool schreiben um Daten zwischen Laptop und PC austauschen zu können. Leider hab ich nun folgendes Problem: irgendwie, wenn [c]BuildClient()[/c] versucht was an den Server zu schicken passiert das senden zwar von der Rückgabe der Prozedur her erfolgreich aber beim Server kommt nicht wirklich was an :|. Hier mal der komplette Code:

Code: Alles auswählen

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;                                     ;;
;;         -= File Manager =-          ;;
;;                                     ;;
;;  Protokoll: Siehe irgendwo auf dem  ;;
;;  Schreibtisch (gilt nur für den     ;;
;;  Programmierer)                     ;;
;;                                     ;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Structure sNetPacket            
    pakBefehl.l                 
    pakLeange.l                 
    pakClientID.s   
    pakGUID.s
    pakData.s               
EndStructure

Structure sClients
    cltGUID.s
    cltUDPID.UDPUserID
    cltReceiveFileID.l
EndStructure

Declare     cMain()
Declare     CPrint(pText.s, Head.b)
Declare     SplitNetPacket(ReceivedPacket.s)
Declare     SendNetPacket(lngBefehl.l, strGUID.s, strData.s, IsClient.b, *UDPClientID.UDPUserID)
Declare.s   Base64Encode(strText.s)
Declare.l   HexToLong(strHex.s)
Declare.s   Base64Decode(strText.s)
Declare     Base64Decoder(b64in$, b64len.l ,*b64out, b64max.l)
Declare     ParseNetPacket(*R_NetPacket.sNetPacket)
Declare.l   CheckGUIDLogedIn(strGUID.s)
Declare     BuildServer()
Declare     BuildClient()
Declare     ParseCommand()

Enumeration 1
    #NETServer
    #NETClient
EndEnumeration

#NewLine = Chr(2)

Global ServerPort.l
Global ServerHost.s
Global ServerPswd.s

Global ClientGUID.s

Global Mode.b

Global sckMain.UDPConnect
Global DummyNetPacket.sNetPacket
Global DummyUser.UDPUserID

NewList ClientPool.sClients()

cMain()
End

Procedure cMain()
    DefType.l Selection
    OpenConsole()
    ConsoleTitle("NetFile")    
    
    UDPInitNetwork()
    CPrint("NetFile - ein Programm von MVXA" + #NewLine, #False)
    ParseCommand()
    If Mode = 0
        CPrint("    1) Build ^CServer" + #NewLine, #False)
        CPrint("    2) Build ^CClient" + #NewLine, #False) 
        CPrint("", #True): Selection = Val(Input()): PrintN("")        
        
        Select Selection
            Case 1
                Mode = #NETServer
                CPrint("Server Port ", #True)
                ServerPort = Val(Input()): PrintN("")
                
                CPrint("Server Passwort ", #True)
                ServerPswd = Input(): PrintN("")
                
                BuildServer()
            
            Case 2
                Mode = #NETClient
                CPrint("Server Host ", #True)
                ServerHost = Input(): PrintN("")
                
                CPrint("Server Port ", #True)
                ServerPort = Val(Input()): PrintN("")
                
                CPrint("Server Passwort ", #True)
                ServerPswd = Input(): PrintN("")
                
                BuildClient()
        EndSelect        
    Else
        Select Mode
            Case #NETServer: BuildServer()
            Case #NETClient: BuildClient()
        EndSelect
    EndIf
    
EndProcedure

Procedure BuildServer()
    ServerHost = IPString(UDPGetLocalIP())
    Debug MD5Fingerprint(@ServerPswd, Len(ServerPswd))
    CPrint("Build Server...", #True)
    If UDPCreateServer(ServerPort, sckMain)
        CPrint("^AOK" + #NewLine, #False)
        UDPStartCaptureEvents(sckMain)
        *ReceiveBuffer = AllocateMemory(1025)
        Repeat
            If UDPDataAvailable(sckMain) <> 0
                UDPReceive(sckMain, *ReceiveBuffer, 1024)
                CPrint(PeekS(*ReceiveBuffer, 1024), #True)
                SplitNetPacket(PeekS(*ReceiveBuffer, 1024))
                ParseNetPacket(DummyNetPacket)
                RtlFillMemory_(*ReceiveBuffer, 1024, 0)
            EndIf
            
            Select Asc(Left(Inkey(), 1))
                Case 27 ; Escape
                    Break
            EndSelect
            
            Delay(1)
        ForEver ; Left(Inkey(), 1) = Chr(27)  
    Else
        CPrint("^CERROR" + #NewLine, #False)
    EndIf    
EndProcedure

Procedure BuildClient()
    DefType.s pstrMD5Password
    
    pstrMD5Password = MD5Fingerprint(@ServerPswd, Len(ServerPswd))
    CPrint("Baue Verbindung zum Server auf", #True)
    If UDPConnectServer(ServerPort, ServerHost, sckMain)
        UDPStartCaptureEvents(sckMain)
        Repeat
            SendNetPacket(0000, "", pstrMD5Password, #True, DummyUser)
            CPrint(".", #False)
            
            Delay(2500)
        Until UDPDataAvailable(sckMain) <> 0        
    EndIf
EndProcedure

Procedure ParseNetPacket(*R_NetPacket.sNetPacket)
    DefType.s MD5PWD, CurDate
    
    Debug *R_NetPacket\pakBefehl
    Select *R_NetPacket\pakBefehl
        Case 0000           ; Connect
            MD5PWD = MD5Fingerprint(@ServerPswd, Len(ServerPswd))
            If *R_NetPacket\pakData = MD5PWD
                AddElement(ClientPool())
                UDPSaveUserID(ClientPool()\cltUDPID, sckMain)
                
                CurDate = Str(Date())
                ClientPool()\cltGUID = MD5Fingerprint(@CurDate, Len(CurDate))
                SendNetPacket(0001, "SERVER_GUID", ClientPool()\cltGUID, #False, ClientPool()\cltUDPID)
                
                CPrint("Neue verbindung durch Client aufgebaut !"+ #NewLine, #True)
            EndIf
        Case 0002           ; Nachricht
            If CheckGUIDLogedIn(*R_NetPacket\pakGUID) <> 0
                CPrint("Client " + Str(CheckGUIDLogedIn(*R_NetPacket\pakGUID)) + ": " + *R_NetPacket\pakData, #True)
            EndIf
    EndSelect
EndProcedure

Procedure ParseCommand()
    DefType.s Befehl, Parameter
    DefType.s Param
    
    Repeat
        Param     = ProgramParameter()
        Befehl    = StringField(Param, 1, "=")
        Parameter = StringField(Param, 2, "=")
        
        Select LCase(Befehl)
            Case "/build"
                Select LCase(Trim(Parameter))
                    Case "server": Mode = #NETServer
                    Case "client": Mode = #NETClient
                EndSelect
            Case "/port"    : ServerPort = Val(Trim(Parameter))
            Case "/host"    : ServerHost = Trim(Parameter)
            Case "/password": ServerPswd = Trim(Parameter)
        EndSelect
    Until Param = ""
EndProcedure

Procedure.l CheckGUIDLogedIn(strGUID.s)
    ForEach ClientPool()
        If ClientPool()\cltGUID = strGUID: ProcedureReturn ListIndex(ClientPool()): EndIf
    Next
    ProcedureReturn #False
EndProcedure

Procedure SplitNetPacket(ReceivedPacket.s)
    DefType.s tmpPacket, tmpNetData, tmpGUID
    DefType.l tmpPacketPtr, tmpLaenge, tmpBefehl
    
    Repeat
        tmpPacketPtr + 1
        tmpPacket = StringField(ReceivedPacket, tmpPacketPtr, Chr(4))
        If tmpPacket <> ""
            Debug tmpPacket
            tmpBefehl  = HexToLong(StringField(StringField(tmpPacket, 1, Chr(1)), 1, Chr(2)))
            tmpLaenge  = HexToLong(StringField(StringField(tmpPacket, 1, Chr(1)), 2, Chr(2)))
            tmpGUID    =           StringField(StringField(tmpPacket, 1, Chr(1)), 3, Chr(2))
            tmpNetData =                       StringField(tmpPacket, 2, Chr(1))
            If Len(tmpNetData) = tmpLaenge 
                Debug "/CMD: " + Str(tmpBefehl) + "/LEN: " + Str(tmpLaenge) + "/GID: " + tmpGUID + "/DAT: " + tmpNetData
                DummyNetPacket\pakBefehl   = tmpBefehl
                DummyNetPacket\pakLeange   = tmpLaenge
                DummyNetPacket\pakClientID = tmpGUID
                DummyNetPacket\pakData     = Base64Decode(tmpNetData)
                Debug Str(Len(DummyNetPacket\pakData)) + "=" + DummyNetPacket\pakData
            Else
                CPrint("^CFehlerhaftes Packet empfangen !", #True)
            EndIf
        EndIf
    Until tmpPacket = ""
EndProcedure

Procedure.b SendNetPacket(lngBefehl.l, strGUID.s, strData.s, IsClient.b, *UDPClientID.UDPUserID)
    DefType.l PaketLen, lngResult
    DefType.s tmpPaket
    
    strData = Base64Encode(strData)
    PaketLen = Len(strData)+Len(strGUID)+32
    *UDPSendBuffer = AllocateMemory(PaketLen)
    tmpPaket = RSet(Hex(lngBefehl), 4, "0")
    tmpPaket = tmpPaket + Chr(2)
    tmpPaket = tmpPaket + RSet(Hex(Len(strData)), 4, "0")
    tmpPaket = tmpPaket + Chr(2)
    tmpPaket = tmpPaket + strGUID
    
    tmpPaket = tmpPaket + Chr(1)
    tmpPaket = tmpPaket + strData
    tmpPaket = tmpPaket + Chr(4)
    PokeS(*UDPSendBuffer, tmpPaket) 
    
    Debug "Sending Buffer: " + PeekS(*UDPSendBuffer)
    Select Client
        Case #True 
            lngResult = UDPSend(sckMain, *UDPSendBuffer, PaketLen)
        Case #False
            lngResult = UDPSendToUser(sckMain, *UDPClientID, *UDPSendBuffer, PaketLen)
        Default
            ProcedureReturn #False
    EndSelect
    Debug "Sending Buffer Result: " + Str(lngResult)
    RtlFillMemory_(*UDPSendBuffer, PaketLen, 0)
    FreeMemory(*UDPSendBuffer)
EndProcedure

Procedure.s Base64Encode(strText.s)
    DefType.s Result
    
    *B64EncodeBufferA = AllocateMemory(Len(strText)+1)
    *B64EncodeBufferB = AllocateMemory((Len(strText)*3)+1)
    
    PokeS(*B64EncodeBufferA, strText)
    Base64Encoder(*B64EncodeBufferA, Len(strText), *B64EncodeBufferB, Len(strText)*3)
    Result = PeekS(*B64EncodeBufferB)
    
    FreeMemory(*B64EncodeBufferA)
    FreeMemory(*B64EncodeBufferB)
    
    ProcedureReturn Result
EndProcedure

Procedure.s Base64Decode(strText.s)
    DefType.s Result
    
    *B64DecodeBuffer = AllocateMemory(Len(strText)+1)
    Base64Decoder(strText, Len(strText), *B64DecodeBuffer, Len(strText))
    Result = PeekS(*B64DecodeBuffer)
    FreeMemory(*B64DecodeBuffer)
    
    ProcedureReturn Result
EndProcedure

Procedure.s GetPCName()
    DefType.s Result
    DefType.l Laenge
    
    Laenge = 255
    Result = Space(Laenge)
    GetComputerName_(@Result, @Laenge)
    
    ProcedureReturn Result
EndProcedure

Procedure Base64Decoder(b64in$, b64len.l ,*b64out, b64max.l)
    *b64in.l = @b64in$ ; <- put this in to use a string as parameter 
    ;convert tables
    For b64x = 0 To 255
        b64asc$ = b64asc$ + Right("0000000" + Bin(b64x),8) + "|"                    ;ASC Binary Code
    Next b64x
    
    b64tab$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" ;base64 Code
    RtlFillMemory_(*b64out,b64max,0)
    
    ;decode
    b64tln = b64len / 4
    
    For b64xln.l = 0 To b64tln -1
        b64bcd$ = PeekS(*b64in+b64xln*4,4)
        
        b64bin$ = ""
        b64pad = 0
        For b64xb = 1 To 4
            b64tcd$ = Mid(b64bcd$,b64xb,1)
            b64num = FindString(b64tab$,b64tcd$,0)        ;base64 to 6 Bit-Code
            If b64num > 0
                If b64num = 65
                    b64pad +1
                EndIf
                b64bin$ +Right("000000" + Bin(b64num-1),6)   ;24 Bit code
            Else
                b64err = 1
                b64xln = b64tln +1
            EndIf
        Next b64xb
        
        For b64xu = 0 To 2-b64pad
            b64bit$ = Mid(b64bin$,1+b64xu*8,8) + "|"
            b64num = FindString(b64asc$,b64bit$,0) /9     ;ASC Code 8 Bit Binary
            PokeS(*b64out+b64buf,Chr(b64num))
            b64buf +1
            If b64buf >b64max
                b64err = 1
                b64xln = b64tln +1
            EndIf
        Next b64xu
        
    Next b64xln
    
    If b64err = 1
        RtlFillMemory_(*b64out,b64max,0)
        b64buf = -1
    EndIf
    ProcedureReturn b64buf
EndProcedure 

Procedure.l HexToLong(strHex.s)
    DefType.l HexLen, ptrI, ZeichenASC, Dec
    DefType.s Zeichen
    
    strHex = UCase(strHex)
    HexLen = Len(strHex)
    
    For ptrI = 0 To HexLen - 1
        Zeichen = Mid(strHex, HexLen - ptrI, 1)
        
        If Asc(Zeichen) >= 65 And Asc(Zeichen) >= 55 + 16
            ProcedureReturn 0
        EndIf        
        
        If Asc(Zeichen) >= 65
            ZeichenASC = 10 + Asc(Zeichen) - 65
        Else
            ZeichenASC = Val(Zeichen)    
        EndIf
        Dec + ZeichenASC * Pow(16, ptrI)
    Next 
    ProcedureReturn Dec
EndProcedure

Procedure CPrint(pText.s, Head.b)
    DefType.l i
    DefType.s Color, tmpStr
    
    CharToOEM_(@pText, @pText)
    If Head = #True
        CPrint("^8> ", #False)
        ConsoleColor(7, 0)
    EndIf
    For i = 1 To Len(pText)
        If Mid(pText, i, 1) = "^"
            Color = UCase(Mid(pText, i + 1, 1))
            
            Select Color
                Case "0": Color = "0"  ; 0   Schwarz -_-
                Case "1": Color = "1"  ; 1   Blau
                Case "2": Color = "2"  ; 2   Grün
                Case "3": Color = "3"  ; 3   Türkis
                Case "4": Color = "4"  ; 4   Rot
                Case "5": Color = "5"  ; 5   Magenta
                Case "6": Color = "6"  ; 6   Braun
                Case "7": Color = "7"  ; 7   Hellgrau (Std.)
                Case "8": Color = "8"  ; 8   Dunkelgrau
                Case "9": Color = "9"  ; 9   Hellblau
                Case "A": Color = "10" ; 10  Hellgrün
                Case "B": Color = "11" ; 11  Cyan
                Case "C": Color = "12" ; 12  Hellrot
                Case "D": Color = "13" ; 13  Helles Magenta
                Case "E": Color = "14" ; 14  Gelb
                Case "F": Color = "15" ; 15  Weiß
                Default:
                    Print(Mid(pText, i, 2))
            EndSelect
            
            ConsoleColor(Val(Color), 0)
            i = i + 1
        ElseIf Mid(pText, i, 1) = #NewLine
            PrintN("")
        Else
            Print(Mid(pText, i, 1))
        EndIf
    Next
    ConsoleColor(7, 0)
EndProcedure
ich weiß, nicht grade das ordentlichste. Enstand an einem Samstag nachmittag. MVXA mein 2. Nick.

Verfasst: 13.12.2004 19:20
von MVXA
hat es wenigstens jemand getestet :| ?

Verfasst: 13.12.2004 23:43
von stbi
LittleFurz hat geschrieben:hat es wenigstens jemand getestet :| ?
:lol:

wenn ich in der zweiten Zeile der ersten Struktur schon einen Variablenname

Code: Alles auswählen

pakLeange.l
lese, dann mache ich da schon nicht weiter, weil ich anderer Leute Tiffpehler (tm) im Code nicht korrigieren mag :roll:

Verfasst: 14.12.2004 12:36
von bobobo
Außerdem .. was ist UDPUserID ?

Verfasst: 14.12.2004 13:07
von stbi
Mal Scherz beiseite, was ist eigentlich Zweck der Übung? Warum ein eigenes Protokoll für UDP erfinden, wenn man TCP nehmen kann? Schon mal den Atomic FTP-Server angeschaut? Und welche Probleme hast Du im Windows Netzwerk, vielleicht lohnt es sich, da mal anzugriefen?

Verfasst: 14.12.2004 13:27
von bobobo
Wieso?

Zweck von PB ist doch anscheinend Api-Befehle und/oder fremdgecodete DLL's möglichst geschickt in GUI zu packen und als EigenCreation auf den Markt zu schmeissen. :twisted:

Da ist ein selbstgehäkeltes Netzwerk-Protokoll doch schon mal ne
Verbesserung :mrgreen:

Verfasst: 14.12.2004 16:26
von MVXA
stbi hat geschrieben:
LittleFurz hat geschrieben:hat es wenigstens jemand getestet :| ?
:lol:

wenn ich in der zweiten Zeile der ersten Struktur schon einen Variablenname

Code: Alles auswählen

pakLeange.l
lese, dann mache ich da schon nicht weiter, weil ich anderer Leute Tiffpehler (tm) im Code nicht korrigieren mag :roll:
warum zum Teufel ist das n Tippfehler o_O ? Und kannst du es mal testen ? Wäre echt nett, danke -_-.
bobobo hat geschrieben:was ist UDPUserID ?
Für den Server, an welchen Client die Daten gesendet wurde. isClient gibt an ob das vom Client gesendet wurde oder nicht. War einfach zufaul für die gleiche aufgabe 2 Funktionen zu schreiben.
stbi hat geschrieben:Mal Scherz beiseite, was ist eigentlich Zweck der Übung? Warum ein eigenes Protokoll für UDP erfinden, wenn man TCP nehmen kann? Schon mal den Atomic FTP-Server angeschaut? Und welche Probleme hast Du im Windows Netzwerk, vielleicht lohnt es sich, da mal anzugriefen?
Ich mag UDP mehr /:->. Außerdem find ich das bischen langweilig nur vordefinierte Funktionen zu benutzen. So kann ich überprüfen ob das Packet richtig angekommen ist und im zweifelsfalle das Packet erneut senden.
bobobo hat geschrieben:Wieso?

Zweck von PB ist doch anscheinend Api-Befehle und/oder fremdgecodete DLL's möglichst geschickt in GUI zu packen und als EigenCreation auf den Markt zu schmeissen.

Da ist ein selbstgehäkeltes Netzwerk-Protokoll doch schon mal ne
Verbesserung
könntest du das vielleicht näher erklären ? Ich raff den Sinn des Textes nicht :freak:

Verfasst: 14.12.2004 16:46
von Laurin
warum zum Teufel ist das n Tippfehler o_O ?
Schon die Benennung der Variablen läßt auf Tippfehler schließen. Ganz einfach weil pakLeange.l Laenge geschrieben werden müsste. Kommt ein Fehler, kommen viele Fehler.
So kann ich überprüfen ob das Packet richtig angekommen ist und im zweifelsfalle das Packet erneut senden.
Wikipedia hat geschrieben:Verbindungslos heißt, es wird nicht erst eine Verbindung zum Gegenüber aufgebaut (Handshaking wie bei TCP), sondern die Daten werden blind zu der Gegenstelle geschickt. Es wird nicht garantiert, dass das Paket ankommt oder dass sie in der gleichen Reihenfolge ankommen, in der sie gesendet wurden. Die Kommunikationspartner können auch nicht feststellen, ob Pakete verloren gingen oder wie lange sie verzögert wurden (Jitter). Eine Anwendung, die UDP nutzt, muss also mit verloren gegangenen und umsortierten Paketen zurecht kommen oder selber für entsprechende Korrekturmaßnahmen aufkommen.
Quelle: Wikipedia
Damit hat sich UDP eigendlich schon erledigt. Kaum einer verwendet das noch.
könntest du das vielleicht näher erklären ? Ich raff den Sinn des Textes nicht
Der Text den du meinst, war purer Sarkasmus.


Greetz Laurin

Verfasst: 14.12.2004 16:52
von MVXA
Laenge kommt von Länge -_-
Und schon mal auf die Idee gekommen das ich über UDP mein eigenes Protokoll definiere ? Kann ich hier bitte meine Idde durchsetzen und eine Antwort bekommen warum der Server nichts vom Client empfängt ?

Verfasst: 14.12.2004 16:55
von Laurin
Kommt denn wenigsten eine Verbindung über TCP zustande? Wenn nicht, installiere das Netzwerk neu.

Sollte TCP funktionieren, liegt der Fehler wahrscheinlich am Code.


Greetz Laurin