TCP Mausübertragung - Ein paar Probleme

Übersicht BlitzBasic Beginners-Corner

Neue Antwort erstellen

GearTechDE

ehemals 'KillerJo96'

Betreff: TCP Mausübertragung - Ein paar Probleme

BeitragSa, Nov 26, 2011 14:41
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo, ich habe mir es jetzt nochmal zugetraut mit TCP und versucht ein kleines test beispiel zu programmieren. Was raus gekommen ist:

Was klappt:
Arrow Übertragung der Koordinaten jedes einzelnen

Was nicht klappt:
Arrow Es passiert alles viel zu langsam !!

also ich habe einen server:
BlitzBasic: [AUSKLAPPEN]

AppTitle "Server"
Graphics 500,200,32,2

Global ServerStream,Timer%

Const Client_Joined = 1
Const Client_Coords = 2
Const Client_Left = 3

Global Server = CreateTCPServer(8000)

If Server <> 0 Then

Color 0,255,0
Print "[System]:> Server wurde gestartet!"
Color 255,255,255

Else

Color 255,0,0
Print "[System]:> Server konnte nicht gestartet werden!"
Color 255,255,255
WaitKey()
End

End If

Repeat

UpdateNetwork()

Until KeyHit(1)
For c.Client = Each Client

CloseTCPStream c\Stream

Next
CloseTCPServer Server
End

Function UpdateNetwork()

ServerStream = AcceptTCPStream(Server)
If ServerStream Then

c.Client = New Client
c\Stream = ServerStream

End If

For c.Client = Each Client

If ReadAvail(c\Stream) Then

Select ReadByte(c\Stream)

Case Client_Joined

c\Name = ReadString(c\Stream)
c\X = ReadFloat(c\Stream)
c\Y = ReadFloat(c\Stream)

For oc.Client = Each Client

If oc\Stream <> c\Stream Then

WriteByte(oc\Stream,Client_Joined)
WriteString(oc\Stream,c\Name)
WriteFloat(oc\Stream,c\X)
WriteFloat(oc\Stream,c\Y)

End If

Next

Color 0,255,0
Print "[System]:> " + c\Name + " hat das Spiel betreten!"
Color 255,255,255

Case Client_Coords

c\Name = ReadString(c\Stream)
c\X = ReadFloat(c\Stream)
c\Y = ReadFloat(c\Stream)

For oc.Client = Each Client

If oc\Stream <> c\Stream Then

WriteByte(oc\Stream,Client_Coords)
WriteString(oc\Stream,c\Name)
WriteFloat(oc\Stream,c\X)
WriteFloat(oc\Stream,c\Y)

End If

Next

Print "[System]:> " + c\Name + " X=" + c\X + " | Y=" + c\Y

Case Client_Left

c\Name = ReadString(c\Stream)

For oc.Client = Each Client

If oc\Stream <> c\Stream Then

WriteByte(oc\Stream,Client_Left)
WriteString(oc\Stream,c\Name)

End If

Next

Color 255,255,0
Print "[System]:> " + c\Name + " hat das Spiel verlassen!"
Color 255,255,255

End Select

End If

Next

End Function

Type Client

Field Stream,Name$,X#,Y#

End Type


und einen client:
BlitzBasic: [AUSKLAPPEN]

AppTitle "Client"
Graphics 400,200,32,2
SetBuffer BackBuffer()
HidePointer()

Local FT = CreateTimer(60)
Global Name$

Const Client_Joined = 1
Const Client_Coords = 2
Const Client_Left = 3

Global Stream = OpenTCPStream("127.0.0.1",8000)

If Stream <> 0 Then

Name = Input("Name:> ")
WriteByte(Stream,Client_Joined)
WriteString(Stream,Name)
WriteFloat(Stream,MouseX())
WriteFloat(Stream,MouseY())
Print "Beigetreten!"

Else

Print "Nicht beigetreten!"
WaitKey()
End

End If

Repeat
Cls

UpdateNetwork()
UpdateMyClient()

Flip 1
WaitTimer(FT)
Until KeyHit(1)
WriteByte(Stream,Client_Left)
WriteString(Stream,Name)
CloseTCPStream Stream
End

Function UpdateNetwork()

If ReadAvail(Stream) Then

Select ReadByte(Stream)

Case Client_Joined

c.Client = New Client
c\Name = ReadString(Stream)
c\X = ReadFloat(Stream)
c\Y = ReadFloat(Stream)
Text c\X,c\Y - 15,c\Name
Oval c\X,c\Y,10,10,1

Case Client_Coords


For c.Client = Each Client

c\Name = ReadString(Stream)
c\X = ReadFloat(Stream)
c\Y = ReadFloat(Stream)

FindClient.Client(c\Name)

Next

Case Client_Left

For c.Client = Each Client

c\Name = ReadString(Stream)
Delete c.Client

Next

End Select

End If

End Function

Function FindClient.Client(C_Name$)

Local c.Client

For c.Client = Each Client

If c\Name$ = C_Name$ Then

Text c\X,c\Y - 15,c\Name
Oval c\X,c\Y,10,10,1

End If

Next

End Function

Function UpdateMyClient()

Color 0,0,255
Text MouseX(),MouseY() - 15,Name
Color 255,255,255
Oval MouseX(),MouseY(),10,10,1

WriteByte(Stream,Client_Coords)
WriteString(Stream,Name)
WriteFloat(Stream,MouseX())
WriteFloat(Stream,MouseY())

End Function

Type Client

Field Name$,X#,Y#

End Type


die miteinander daten austauschen, leider funktioniert das meist viel zu langsam oder auch garnicht. und es hängt sich bei mir alles nach einer zeit auf -.-

ich wollte euch fragen, was hier das problem sein könnte, denn ich bin beide codes jetzt schon seid 2 stunden am durchsuchen und zu überlegen was ich da und da verbessern kann, aber solangsam fällt mir echt nichts mehr ein.

könnt ihr mir helfen?
Mit freundlichen Grüßen: GearTechDE

ToeB

BeitragSa, Nov 26, 2011 14:56
Antworten mit Zitat
Benutzer-Profile anzeigen
Also ich weiß nicht ob du dich da n bissel mehr beschäftigt hast mit UDP oder TCP, aber TCP ist ein Protokoll welches zuerst immer prüft, ob die Nachricht beim Empfänger gelandet ist. Und das kann unter Umständen sehr zeitaufwendig werden. Deswegen solltest du für Positions-Übertragungen auch lieber UDP nehmen. Dort ist zwar nicht gewährleistet, das jede Nachricht ankommt, ist dafür aber umso schneller. Du kannst dir damit auch selber ein Protokoll basteln, welches ähnlich funktioniert wie TCP, nur das die Nachrichten nicht das Programm an sich blockieren sondern der Sendevorgang im Hintergund abläuft (Kannst dir dazu ja mal meine SimpleUDP3.0 angucken -> Signatur).

Lg
Religiöse Kriege sind Streitigkeiten erwachsener Männer darum, wer den besten imaginären Freund hat.
Race-Project - Das Rennspiel der etwas anderen Art
SimpleUDP3.0 - Neuste Version der Netzwerk-Bibliothek
Vielen Dank an dieser Stelle nochmal an Pummelie, welcher mir einen Teil seines VServers für das Betreiben meines Masterservers zur verfügung stellt!

GearTechDE

ehemals 'KillerJo96'

BeitragSa, Nov 26, 2011 15:20
Antworten mit Zitat
Benutzer-Profile anzeigen
Leider ist mein Problem, das ich weder mit UDP und noch deiner Simple UDP (was ziemlich dumm ist) nicht klarkomme. Warum auch immer, ich versteh es einfach nicht.
Mit freundlichen Grüßen: GearTechDE

ToeB

BeitragSa, Nov 26, 2011 16:24
Antworten mit Zitat
Benutzer-Profile anzeigen
Bei der SimpleUDP sind Beispiel Dabei, da kannst du sehen welche Befehle wofür sind.

Zum Hosten eines Spiels (Server):
Code: [AUSKLAPPEN]
UDP_SessionCreate( SpielerAnzahl, Modus=NETSESSION, Port )


Zum Joinen auf einen Host (Server):
Code: [AUSKLAPPEN]
UDP_SessionConnect( ServerIP$, ServerPort, Holepunching=False )


Umbedingt ausführen (in der Hauptschleife):
Code: [AUSKLAPPEN]
UDP_SessionUpdate( )


Das sind die Grundlagen. Um Nachrichten zu senden,
Code: [AUSKLAPPEN]
UDP_wByte( Byte )
UDP_wShort( Short )
UDP_wInt( Int )
UDP_wFloat( float )
UDP_wString( Str$ )
UDP_SendMsg( Header, ClientID=SENDTO_ALL, Modus=SEND_Normal )

Das ganze ist so gedacht, das du in eine Nachricht gleich mehrere Daten gleichzeitig abschicken kannst. Einfach das Gewünschte reinschreiben und mit UDP_SendMsg absenden. In deinem Beispiel:
Code: [AUSKLAPPEN]
UDP_wInt( MouseX() )
UDP_wInt( MouseY() )
UDP_SendMsg( 5, SENDTO_ALL, SEND_Normal )


Um diese Nachrichten zu Empfangen, einfach so prüfen :
Code: [AUSKLAPPEN]
While UDP_RecvMsg( ) ;Ob eine Nachricht empfangen wurde
      tmpID = UDP_MsgFromID( ) ;Von welchem Spieler die Nachricht ist
      tmpHeader = UDP_MsgHeader( ) ;Welche NachrichtenID die Nachricht hat
      Select tmpHeader
         Case 5 ;Header oben bei SendMsg angegeben
            p_MouseX( tmpID ) = UDP_rInt( ) ;Aus der Nachricht einen Integer auslesen
            p_MouseY( tmpID ) = UDP_rInt( )
      End Select
   Wend 


Für genaueres kannst du ja mal das Beispiel "Sample #01 - Verbinden" angucken.

Lg
Religiöse Kriege sind Streitigkeiten erwachsener Männer darum, wer den besten imaginären Freund hat.
Race-Project - Das Rennspiel der etwas anderen Art
SimpleUDP3.0 - Neuste Version der Netzwerk-Bibliothek
Vielen Dank an dieser Stelle nochmal an Pummelie, welcher mir einen Teil seines VServers für das Betreiben meines Masterservers zur verfügung stellt!

Propellator

BeitragSa, Nov 26, 2011 16:24
Antworten mit Zitat
Benutzer-Profile anzeigen
Dein Problem liegt eher darin, dass du jedesmal eine riesige Menge an Daten durchboxt.
Der String als Client-Identifikation brauchst du eigentlich nicht jedesmal mitzusenden, und normalerweise sendet man nicht bei jeder Bewegung die ganze Position sondern sendet eine Veränderung bzw. die Richtung und interpoliert dann, das eigentliche syncen der gesamten Position findet nur alle x Millisekunden statt.

Jedoch könntest du dir mal UDP ansehen. Bei Positionsdaten musst du dir keinen Kopf um Paketverluste machen. Wenns hart auf hart kommt, kannst du immer noch die "ENet" library verwenden, die ist ganz bequem.

MfG

PS: @ToeB: Schamlose Werbung much?
Propellator - Alles andere ist irrelephant.
Elefanten sind die Könige der Antarktis.

GearTechDE

ehemals 'KillerJo96'

BeitragSa, Nov 26, 2011 19:04
Antworten mit Zitat
Benutzer-Profile anzeigen
Zitat:

PS: @ToeB: Schamlose Werbung much?


-> xD lol

Naja ich denke mal ich will aber generell lernen wie man UDP benutz und mir nich irgendwelche funktionen abnehmen lassen -.-

Dann guck ich mir lieber noch ein paar udp beispiele an und versuch daraus zu lernen

trotzdem danke
Mit freundlichen Grüßen: GearTechDE

ToeB

BeitragSa, Nov 26, 2011 20:41
Antworten mit Zitat
Benutzer-Profile anzeigen
@Propellator Lesen ist auch nicht grad einer deiner Stärken oder ?
Zitat:
Kannst dir dazu ja mal meine SimpleUDP3.0 angucken -> Signatur

Ich deute ihn lediglich darauf hin, meine Lib anzugucken, da sie ein "Modul" für das Senden von UDP-Nachrichten enthält, welches sicherstellt das die Nachrichten auch ankommen. In meinem zweiten Post wollte ich ihm nur zeigen, wie die Grundschritte aussehen, da er meinte er komme damit nicht klar. Also nix schamlose Werbung.

@Killerjo69:
Dann schreib doch einfach "Ich wills lernen" und ich hätte mir den Post oben auch sparen können.

lg
Religiöse Kriege sind Streitigkeiten erwachsener Männer darum, wer den besten imaginären Freund hat.
Race-Project - Das Rennspiel der etwas anderen Art
SimpleUDP3.0 - Neuste Version der Netzwerk-Bibliothek
Vielen Dank an dieser Stelle nochmal an Pummelie, welcher mir einen Teil seines VServers für das Betreiben meines Masterservers zur verfügung stellt!

GearTechDE

ehemals 'KillerJo96'

BeitragSo, Nov 27, 2011 11:34
Antworten mit Zitat
Benutzer-Profile anzeigen
Zitat:
Dann schreib doch einfach "Ich wills lernen" und ich hätte mir den Post oben auch sparen können.


ja tut mir leid ^^ hat vielleicht einer ein simples udp tutorial? ich finde momentan keins -.-
Mit freundlichen Grüßen: GearTechDE

Propellator

BeitragSo, Nov 27, 2011 14:53
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi, der Hilfeartikel zu CreateUDPStream hat zwar ein Beispiel, aber hier noch eine kleine weitergehende Ausführung:

1. Ein UDP-Stream hat keine feste Zieladresse und keinen festen Zielport. (Der lokale Port kann entweder manuell oder automatisch gewählt werden.)

2. Ein UDP-Stream unterscheidet nicht zwischen Server und Client. Er kann immerhin Nachrichten von mehreren Quellen entgegennehmen und auch an mehrere Quellen verschicken.

3. Ein UDP-Stream stellt nicht sicher, dass wirklich eine Verbindung besteht. Es gibt keinen Handshake, und es wird nicht garantiert dass Pakete in der richtigen Reihenfolge oder überhaupt ankommen.

So funktionierts also:
Senden:
Mit WriteByte, WriteInt, etc. etwas in den Stream schreiben. Wenn das Paket deiner Meinung nach fertig geschrieben wird, kannst du dies mit SendUDPMsg an eine Ziel-IP und einen Ziel-Port verschicken.

Empfangen:
Zuerst musst du das Paket mit RecvUDPMsg empfangen. Mit UDPMsgIP erhältst du den Absender, mit UDPMsgPort den Port von welchem aus die Nachricht gesendet wurde. (Nicht der, auf dem die Nachricht empfangen wurde!)

Wichtig! "ip" ist immer eine IP im Integer-Format. Diese kannst du so erhalten:
BlitzBasic: [AUSKLAPPEN]
HostIP(CountHostIPs("eine.normale.string.ip"))


MfG

Propellator

PS: @ToeB: NO U.
Propellator - Alles andere ist irrelephant.
Elefanten sind die Könige der Antarktis.

Midimaster

BeitragSo, Nov 27, 2011 16:56
Antworten mit Zitat
Benutzer-Profile anzeigen
also... ich kann mir nicht vorstellen, dass die paar pippi-Daten, die hier zu senden sind unter TCP wirklich zu timing-problemen führen.

Es gibt hier zwar eine "nur UDP macht Sinn"-Fraktion, die alle anderen Protokolle gerne zum Bereich "Kommunikation durch Brieftauben" einordnen möchte, ich aber rate Dir den Fehler wo anders zu suchen!

Durch das Takten mit 60Hz und Flip 1 kommen die Clients viel zu selten dazu die Nachrichten auszuwerten. Außerdem werden bei Deinem Code die Mausdaten (obwohl unverändert) zuoft wiederholt gesendet. Straffe dies und sende nur im Bedarfsfall. Das dürfte reichen, um die Performance ausreichend zu steigern.
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe

Holzchopf

Meisterpacker

BeitragSo, Nov 27, 2011 17:05
Antworten mit Zitat
Benutzer-Profile anzeigen
Midimaster hat Folgendes geschrieben:
also... ich kann mir nicht vorstellen, dass die paar pippi-Daten, die hier zu senden sind unter TCP wirklich zu timing-problemen führen.


Nicht in der Datenmenge liegt das Problem, sondern in BlitzBasics Implementation von TCP. Wie bereits erwähnt wurde, wird bei jedem gesendeten Datenpaket kontrolliert, ob dieses ankam und dessen Erhalt sichergestellt. Solange das Paket unterwegs ist, macht BlitzBasic Nichts anderes als den Datentransfer sicherzustellen. Und Pakete sind im Internet immer lange unterwegs. Relativ gesehen. 16ms reichen zumindest nicht, um das Paket zu senden und auf den Erhalt zu warten - ergo sind FPS-Zahlen von 60 unter Verwendung von TCP in BlitzBasic nicht realisierbar.

Aus diesem Grund:
Für reine Chats oder Rundenbasierte Spiele: TCP
Für Spiele, bei denen es auf die Geschwindigkeit ankommt: UDP
Erledige alles Schritt um Schritt - erledige alles. - Holzchopf
CC BYBinaryBorn - Yogurt ♫ (31.10.2018)
Im Kopf da knackt's und knistert's sturm - 's ist kein Gedanke, nur ein Wurm

Midimaster

BeitragMo, Nov 28, 2011 10:43
Antworten mit Zitat
Benutzer-Profile anzeigen
ah, jetzt glaub ich hab ich das zum ersten Mal richtig verstanden! Danke Hozchopf!

Wäre dann eine logische Optimierung (vorausgesetzt man würde unbedingt TCP verwenden wollen), dass man die zu versendenen Daten in ein Bündel schnürt und dann mit nur einem WriteString() versendet?

Und sehe ich das jetzt so richtig: Keine TCP Nachricht kann schneller in BB verarbeitet werden als ein Ping zwischen den beiden Computern an Zeit benötigt? Als in einem internen Netzwerk sind zwar <5msec möglich, aber via Internet könnten es auch >100msec werden?

Gilt dies auch so für BMax?
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe

BladeRunner

Moderator

BeitragMo, Nov 28, 2011 12:10
Antworten mit Zitat
Benutzer-Profile anzeigen
Nein, BMax blockiert nicht.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

ToeB

BeitragMo, Nov 28, 2011 15:28
Antworten mit Zitat
Benutzer-Profile anzeigen
Besser wäre dann du nimmst ne Bank und schreibst mit WriteBytes, damit kannst du dir die 4 Byte Längenangabe sparen ;D

mfg ToeB
Religiöse Kriege sind Streitigkeiten erwachsener Männer darum, wer den besten imaginären Freund hat.
Race-Project - Das Rennspiel der etwas anderen Art
SimpleUDP3.0 - Neuste Version der Netzwerk-Bibliothek
Vielen Dank an dieser Stelle nochmal an Pummelie, welcher mir einen Teil seines VServers für das Betreiben meines Masterservers zur verfügung stellt!

Neue Antwort erstellen


Übersicht BlitzBasic Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group