Simpler UDP-Datenaustausch funktioniert nicht

Übersicht BlitzBasic Allgemein

Neue Antwort erstellen

draco

Betreff: Simpler UDP-Datenaustausch funktioniert nicht

BeitragMi, Aug 13, 2008 16:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Guten Tag liebe Forengemeinde,
Nachdem ich mir Rob's Netzwerkkapitel aus seinem Tutorial und weitere Chat-Codeschnippsel hier aus dem Forum länger angesehen und studiert habe, wollte ich einen UDP-Datenaustausch von Grund auf mal selber schreiben.

Code Client:
Code: [AUSKLAPPEN]
Graphics3D 800,600,16,2
SetBuffer BackBuffer()

   SEND_PORT = 8001
   RECV_PORT = 8000
   SEND_STREAM = CreateUDPStream(SEND_PORT)
   RECV_STREAM = CreateUDPStream(RECV_PORT)
Print "Deine IP ist: 5.240.239.156, irgendeine taste drücken!"
WaitKey()
Cls
While Not KeyHit(1)

Text 10,10,"Drücke leertaste um eine nachricht mit einem byte inhalt zu senden"

If KeyHit(57) Then
   WriteString SEND_STREAM,"Thilo sendet ein Byte"
   SendUDPMsg SEND_STREAM,"5.13.130.86"
   Print "du hast was gesendet"
EndIf

If RecvUDPMsg(RECV_STREAM)
   Print ReadString(RECV_STREAM)
EndIf

Flip
Wend
End


Code Host:
Code: [AUSKLAPPEN]
Graphics3D 800,600,16,2
SetBuffer BackBuffer()

   SEND_PORT = 8000
   RECV_PORT = 8001
   SEND_STREAM = CreateUDPStream(SEND_PORT)
   RECV_STREAM = CreateUDPStream(RECV_PORT)

Print "client ip: 5.240.239.156"
WaitKey()
Cls
While Not KeyHit(1)

Text 10,10,"Drücke leertaste um eine nachricht mit einem byte inhalt zu senden"

If KeyHit(57) Then
   WriteString SEND_STREAM,"Rob sendet ein Byte"
   SendUDPMsg SEND_STREAM,"5.240.239.156"
   Print "du hast was gesendet"
EndIf

If RecvUDPMsg(RECV_STREAM)
   Print ReadString(RECV_STREAM)
EndIf

Flip
Wend
End


Ich will wirklich nur das simpelste, daher kein chat. (Die IP's sind Hamachi-IP's, meine Testperson sitzt ein paar Kilometer entfernt Wink ) Nun kommen aber keine der querys an..

Ich hoffe ihr könnt mir helfen und stempelt mich nicht als Tutorial-überleser bzw. Boardsuchen-vermeider ab Razz
Die einzige Möglichkeit, etwas vom Leben zu haben, ist, sich mit aller Macht hineinzustürzen...
 

Dreamora

BeitragMi, Aug 13, 2008 16:21
Antworten mit Zitat
Benutzer-Profile anzeigen
Weiss nicht inwiefern da dran hamachi was ändert aber:

1. Du musst normalerweise für UDP portforwarding in deinem router einrichten, damit es dein computer erreicht ausser du machst nen php / cgi basierenden masterserver der NAT punchthrough ermöglicht

2. Software Firewall muss gegebenenfalls ebenfalls angepasst werden
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.

draco

BeitragMi, Aug 13, 2008 16:38
Antworten mit Zitat
Benutzer-Profile anzeigen
Nein, also UDP funktioniert über Hamachi mit den beiden IP's, zumindest funktioniert dieser code, der hier aus dem Forum stammt:

Code: [AUSKLAPPEN]
Graphics3D 800,600,16,2
SetBuffer BackBuffer()

Global p_anz = 1
Global Server = 0
Global send_ms = MilliSecs() ;Variable fürs Senden, damit nicht jeden schleifen durchgang gesendet werden muss
Global Send_in = 25 ;Intervallen, in denen gesenden wird (in ms)
Global SEND_STREAM
Global RECV_STREAM
Global SEND_PORT
Global RECV_PORT
Global GET_MSG

Const MSG = 1
Const QUEST = 2
Const NO_P = 3
Const GET_HOST = 4

Dim Cl$(39)

Dim acc(p_anz),name$(p_anz),IP(p_anz),TimeOut(p_anz),New_p(p_anz)  ;Die Wichtigsten Functionen

Dim chat$(p_anz),SetChat(P_anz) ;Positionen im Spiel (Hier ein Chat)

Dim GETHOST_IP(64)
Dim GETHOST_N$(64)

;HOST / JOIN Abfrage :
Print "HOST(1)  /  JOIN(2)"
Server = Input(">>")
If Server < 1 Then Server = 1 ;HOST
If Server > 2 Then Server = 2 ;JOIN

;Weitere Abfragen :
Select Server
Case 1
   SEND_PORT = 8000
   RECV_PORT = 8001
   ;Namen :
   Print "Name : "
   Name_$ = Input(">>")
   ;Spieleranzahl :
   Print "Spieler anzahl : "
   Print "1 : 4"
   Print "2 : 8"
   Print "3 : 16"
   Print "4 : 24"
   Print "5 : 32"
   Print "6 : 64"
   p_anz = Input(">>")
   If p_anz < 1 Then p_anz = 1
   If p_anz > 6 Then p_anz = 6
   Select p_anz
   Case 1
      p_anz = 4
   Case 2
      p_anz = 8
   Case 3
      p_anz = 16
   Case 4
      p_anz = 24
   Case 5
      p_anz = 32
   Case 6
      p_anz = 64
   End Select
   DimNew(p_anz)
   SEND_STREAM = CreateUDPStream(SEND_PORT)
   RECV_STREAM = CreateUDPStream(RECV_PORT)
   acc(1) = 1
   Name(1) = Name_
   ID = 1
Case 2
   SEND_PORT = 8001
   RECV_PORT = 8000
   SEND_STREAM = CreateUDPStream(SEND_PORT)
   RECV_STREAM = CreateUDPStream(RECV_PORT)
   ;Namen :
   Print "Name : "
   Name_$ = Input(">>")
   Print "Was willst du tun ?"
   Print "1 : IP eingeben"
   Print "2 : IP aus Liste auswählen"
   wahl = Input(">>")
   If wahl < 1 Then wahl = 1
   If wahl > 2 Then wahl = 2
   Select wahl
   Case 1
      Print "Server IP : "
      IP(1) = INT_IP(Input(">>"))
   Case 2
      IP(1) = INT_IP(BroadcastIP())
      WriteByte(SEND_STREAM,GET_HOST)
      SendUDPMsg(SEND_STREAM,IP(1),SEND_PORT)
      wahl = 0
      Cls
      Locate 0,0
      Print "Drücke enter um einen auszuwählen"
      Delay 100
      FlushKeys()
      Repeat
         If RecvUDPMsg(RECV_STREAM)
            If ReadByte(RECV_STREAM) = GET_HOST Then
               If wahl < 64 Then
                  namen$ = ReadString(RECV_STREAM)
                  wahl = wahl + 1
                  GETHOST_IP(wahl) = UDPMsgIP(RECV_STREAM)
                  GETHOST_N$(wahl) = namen
                  Print wahl + " : "+GETHOST_N$(wahl)+" ("+DottedIP(GETHOST_IP(wahl))+")"
               EndIf
            EndIf
         EndIf
         If KeyHit(1) Then End
      Until KeyHit(28)
      max_wa = wahl
      Delay 100
      FlushKeys()
      Print "Deine Wahl : "
      wahl = Input(">>")
      If wahl < 1 Then wahl = 1
      If wahl > max_wa Then wahl = max_wa
      IP(1) = GETHOST_IP(wahl)
   End Select
   WriteByte(SEND_STREAM,QUEST)
   WriteString(SEND_STREAM,Name_$)
   SendUDPMsg(SEND_STREAM,IP(1),SEND_PORT)
   Print "Bitte Warten..."
   wait_ms = MilliSecs() + 1000
   Repeat
      If RecvUDPMsg(RECV_STREAM)
         If ReadByte(RECV_STREAM) = QUEST
            ID = ReadByte(RECV_STREAM)
            p_anz = ReadByte(RECV_STREAM)
            IPIP = IP(1)
            DimNew(p_anz)
            IP(1) = IPIP
            acc(ID) = 1
            Name(ID) = Name_
            For i = 1 To p_anz
               IDID = ReadByte(RECV_STREAM)
               name(IDID) = ReadString(RECV_STREAM)
               acc(IDID) = 1
               TimeOut(IDID) = MilliSecs() + 1000
            Next
            Exit
         Else
            Print "Serverliste voll !"
            Delay 2500
            End
         EndIf
      EndIf
      If wait_ms <= MilliSecs()
         Print "Server hat nicht geantwortet !"
         Delay 2500
         End
      EndIf
      If KeyHit(1) Then End
   Forever   
   GET_MSG = 1
End Select
;zz = acc(1)

;Schleife
Repeat

      ;testquadrat bewegen immoment unnötig
      Color 255,255,255
      Rect p1_x,p1_y,10,10
      
      If KeyDown(200) Then p1_y = p1_y - 1
      If KeyDown(208) Then p1_y = p1_y + 1
      If KeyDown(205) Then p1_x = p1_x + 1
      If KeyDown(203) Then p1_x = p1_x - 1
   ;Hier die ganzen Steuerungs-abfragen, etc...
   zeile = 0
   For i = 1 To p_anz
      If acc(i) Then
         Text 0,zeile*15,i+".: "+Name(i)
         zeile = zeile + 1
      EndIf
   Next
   g = GetKey()
   If g > 0 And g <> 8 And g <> 13 Then Ch$ = Ch$ + Chr(g)
   If g = 8 Then Ch$ = Left(Ch$,Len(Ch$)-1)
   If g = 13 And ch <> "" Then
      Chat(ID) = ch
      ch = ""
      NewChatLine(Name(ID)+":"+Chat(ID))
   EndIf
   For i =1 To p_anz
      If i <> ID And Chat(i) <> "" And SetChat(i) = 0
         NewChatLine(Name(i)+":"+Chat(i))
         If Server = 1
            SetChat(i) = 1
         Else
            Chat(i) = ""
         EndIf
      EndIf
   Next
   Text 150,0,"Chat:"+ch
   Rect 150,15,650,1
   For i = 1 To 39
      Text 150,0+i*15,cl(i)
   Next
   ;Hier das ganze senden von Dateien
   Select Server
   Case 1
      If send_ms <= MilliSecs() Then
         For SEND_PLAYER = 2 To p_anz ;An die Spieler senden
            If acc(SEND_PLAYER) = 1 Then ;Wenn Player online ist
               WriteByte(SEND_STREAM,MSG) ;BYte für normal Nachricht (Positionen etc...)
               For POS_PLAYER = 1 To p_anz ;Positionen von Spielern
                  If POS_PLAYER <> SEND_PLAYER ;Damit keiner seine eigenen Daten bekommt und sich daher nicht bewegen (o.ä.) kann ^^
                     If acc(POS_PLAYER) = 1 Then
                        WriteByte(SEND_STREAM,POS_PLAYER) ;ID vom aktuellen Player als erstes schiken
                        ;Hier weitere Sachen schiken
                        WriteString(SEND_STREAM,Chat(POS_PLAYER))
                        If New_p(POS_PLAYER) = 1 Then WriteString(SEND_STREAM,name(POS_PLAYER))
                        ;/\__--Ist wenn ein neuer Spieler
                        ;dazugekommen ist, damit die anderen wissen, wie er heißt (man kann zusätzlich auch noch andere Standart-
                        ;informationen senden, die nicht die ganze Zeit mitgesendet werden müssen, weil sie immer gleich bleiebn,
                        ;z.b. Farbe oder Team...
                     EndIf
                  EndIf
               Next
               SendUDPMsg(SEND_STREAM,IP(SEND_PLAYER),SEND_PORT) ;Alles senden
            SendUDPMsg(SEND_Pos,IP(SEND_PLAYER),SEND_PORT) ;position
            EndIf
         Next
         For i = 1 To p_anz
            New_p(i) = 0
            Chat(i) = ""
            SetChat(i) = 0
         Next
         send_ms = MilliSecs() + send_in ;Wieder zurücksetzten, damit der Intervall auch bleibt
      EndIf
   Case 2
      If GET_MSG = 1 Then ;Wenn der CLIENT eine Nachricht vom Host erhalten hat...
         WriteByte(SEND_STREAM,MSG) ;Normale Nachricht
         WriteByte(SEND_STREAM,ID);Eigene ID
         ;Andere Daten...
         WriteString(SEND_STREAM,Chat(ID))
         SendUDPMsg(SEND_STREAM,IP(1),SEND_PORT)
         CHAT(ID) = ""
         GET_MSG = 0
      EndIf
   End Select
   ;Hier die ganzen Daten empfangen / verarbeiten
   While RecvUDPMsg(RECV_STREAM) ;Während empfamngen wird, schleife nicht beenden...
      byte = ReadByte(RECV_STREAM) ;Byte für orientierung
      Select Server
      Case 1
         Select byte
         Case MSG ;Normale Nachricht
            IDID = ReadByte(RECV_STREAM) ;ID des Clienten auslesen
            ;Andere sachen für ID : IDID auslesen
            Chat(IDID) = ReadString(RECV_STREAM)
            TimeOut(IDID) = MilliSecs() + 1000 ;TimeOut wieder auf 1 Sekunde setzten
         Case QUEST
            ;Gucken, ob noch ein platz frei ist, und dann welcher
            IDID = 0
            For i = 2 To p_anz
               If acc(i) = 0 Then IDID = i:Exit
            Next
            If IDID Then ;Wenn platzt frei
               Name(IDID) = ReadString(RECV_STREAM) ;NAmen auslesen
               New_p(IDID) = 1
               acc(IDID) = 1
               IP(IDID) = UDPMsgIP(RECV_STREAM) ;IP herausfinden
               WriteByte(SEND_STREAM,QUEST)
               WriteByte(SEND_STREAM,IDID)
               WriteByte(SEND_STREAM,p_anz)
               For i = 1 To p_anz
                  If i <> IDID And acc(i)
                     WriteByte(SEND_STREAM,i)
                     WriteString(SEND_STREAM,name(i))
                  EndIf
               Next
               SendUDPMsg(SEND_STREAM,IP(IDID),SEND_PORT)
               TimeOut(IDID) = MilliSecs() + 1000 ;TimeOut auf 1 Sekunde setzten
            Else ;Wenn kein Platzt frei
               WriteByte(SEND_STREAM,NO_P) ;Sende "Kein Platzt"
               SendUDPMsg(SEND_STREAM,UDPMsgIP(RECV_STREAM),SEND_PORT)
            EndIf
         Case GET_HOST
            max_p = 0
            For i = 1 To p_anz
               If acc(i) Then max_p = max_p + 1
            Next
            namen$ = name(1)+"  "+max_p+"/"+p_anz
            WriteByte(SEND_STREAM,GET_HOST)
            WriteString(SEND_STREAM,namen$)
            SendUDPMsg(SEND_STREAM,UDPMsgIP(Recv_STREAM),SEND_PORT)
         End Select         
      Case 2
         Select byte
         Case MSG
            While Not Eof(RECV_STREAM)
               IDID = ReadByte(RECV_STREAM) ;ID auslesen
               If IDID > 0
                  chat(IDID) = ReadString(RECV_STREAM)
                  If acc(IDID) = 0 Then ;Wenn die ID vorher nicht online war ...
                     acc(IDID) = 1 ;Online machen xD
                     name(IDID) = ReadString(RECV_STREAM)
                     ;Oder halt noch die Standartinformationen (siehe oben bei Senden...)
                  EndIf
                  TimeOut(IDID) = MilliSecs() + 1000 ;TimeOut wieder auf 1 Sekunde setzten
               EndIf
            Wend
            GET_MSG = 1 ;Nachricht bekommen
         End Select             
      End Select
      If KeyHit(1) Then End


   Wend
     
   ;TimeOut :
   For i = 1 To p_anz
      If acc(i) And i <> ID ;Wenn online aber nicht die eigene IP
         If TimeOut(i) <= MilliSecs() Then acc(i) = 0 ;Wenn TimeOut (1s) abgelaufen, rausschmiss
      EndIf
   Next
   ;Timeout heiß so viel wie dass man 1s lang keine nachricht mehr von dem jenigen bekommen hat, heit er hat ca 40 nachrichten
   ;nicht bekommen von ihm...
   If acc(1) = 0 ; Wenn Server nicht mehr da ...
      Cls
      Flip
      Text 400,100,"Server hat das Spiel verlassen...",1
      Text 400,400,"-Taste zum Beenden drücken-",1
      Delay 100
      WaitKey()
      End ; ...Beenden ^^
   EndIf   
   Flip
   Cls

Until KeyHit(1)
End


Function INT_IP(IP$)
   If Instr(IP$,".") <> 0 a1=Int(Left(IP$,Instr(IP$,".")-1)):IP$=Right(IP$,Len(IP$)-Instr(IP$,"."))
   If Instr(IP$,".") <> 0 a2=Int(Left(IP$,Instr(IP$,".")-1)):IP$=Right(IP$,Len(IP$)-Instr(IP$,"."))
   If Instr(IP$,".") <> 0 a3=Int(Left(IP$,Instr(IP$,".")-1)):IP$=Right(IP$,Len(IP$)-Instr(IP$,"."))
   a4=Int(IP$)
   Return (a1 Shl 24) + (a2 Shl 16) + (a3 Shl 8 ) +a4
End Function
         
                 

Function DimNew(NewAnz)
   
   p_anz = NewAnz
   Dim acc(p_anz),name$(p_anz),IP(p_anz),TimeOut(p_anz),New_p(p_anz)  ;Die Wichtigsten Functionen
   
   Dim Chat(p_anz),SetChat(p_anz)  ;Positionen im Spiel (Hier Chat)
   
End Function

Function BroadcastIP$()
 
   CountHostIPs("")
   Local IP$ = DottedIP(HostIP(1))
   
   Local Subnetmask$ = "255.255.255.0"
   
   Local IPDigits[3], SubnetDigits[3]
   Local pos, i
   
   ; IP aufteilen
   For i = 0 To 3
      pos = Instr( IP$, "." )
      If pos > 0
         IPDigits[i] = Left( IP$, pos -1 )
         IP$ = Mid( IP$, pos +1 )
      Else
         IPDigits[i] = IP$
      EndIf
   Next
   
   ; Subnetmask aufteilen &invertieren
   For i = 0 To 3
      pos = Instr( Subnetmask$, "." )
      If pos > 0
         SubnetDigits[i] = Left( Subnetmask$, pos -1 ) Xor $FF
         Subnetmask$ = Mid( Subnetmask$, pos +1 )
      Else
         SubnetDigits[i] = Subnetmask$ Xor $FF
      EndIf
   Next
   
   ; IP maskieren
   For i = 0 To 3
      IPDigits[i] = IPDigits[i] Or SubnetDigits[i]
   Next
   
   Return IPDigits[0] +"." +IPDigits[1] +"." +IPDigits[2] +"." +IPDigits[3]
   
End Function

Function NewChatLine(txt$)
   
   If txt$ <> ""
      For i = 39 To 1 Step -1
         cl(i) = cl(i-1)
      Next
      cl(1) = txt$
   EndIf
   
End Function
Die einzige Möglichkeit, etwas vom Leben zu haben, ist, sich mit aller Macht hineinzustürzen...
 

JanK

BeitragMi, Aug 27, 2008 23:21
Antworten mit Zitat
Benutzer-Profile anzeigen
Falls das hier noch aktuell ist:
Du solltest nicht vergessen, dass Sendudpmsg eine Integer-IP benötigt!

Sehr nützliche Funktion:
Code: [AUSKLAPPEN]
Function INT_IP(IP$)
   If Instr(IP$,".") <> 0 a1=Int(Left(IP$,Instr(IP$,".")-1)):IP$=Right(IP$,Len(IP$)-Instr(IP$,"."))
   If Instr(IP$,".") <> 0 a2=Int(Left(IP$,Instr(IP$,".")-1)):IP$=Right(IP$,Len(IP$)-Instr(IP$,"."))
   If Instr(IP$,".") <> 0 a3=Int(Left(IP$,Instr(IP$,".")-1)):IP$=Right(IP$,Len(IP$)-Instr(IP$,"."))
   a4=Int(IP$)
   Return (a1 Shl 24) + (a2 Shl 16) + (a3 Shl 8 ) +a4
End Function

Arrow
Neuer Code:
Code: [AUSKLAPPEN]
If KeyHit(57) Then
   WriteString SEND_STREAM,"Thilo sendet ein Byte"
   SendUDPMsg SEND_STREAM,[b]INT_IP("5.13.130.86")[/b]
   Print "du hast was gesendet"
EndIf
Ich habe keine Zeit, mich zu beeilen.
The Pollux Conflict || The Pollux Renegades || Lipstick-live.de

Neue Antwort erstellen


Übersicht BlitzBasic Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group