Probleme mit meinem Spiel übers Netzwerk oder Internet?

Übersicht BlitzMax, BlitzMax NG Allgemein

Neue Antwort erstellen

 

bruce85

Betreff: Probleme mit meinem Spiel übers Netzwerk oder Internet?

BeitragFr, März 09, 2012 0:54
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo nochmal,
ich würde gerne meine Betaversion von Batak "Multiplayer" veröffentlichen, leider funktioniert es zurzeit nur Lokal auf einem Rechner Problemlos.
Wenn ich das Spiel mit Freunden Testen möchte übers Internet, dann hängt sich das Spiel bei den Clienten ab und zu auf, sobald der Server ein bestimmtes Datenpaket sendet.

Lokal auf einem Rechner funktioniert es einwandfrei, was mich wundert ist, das es übers Internet nicht so richtig funktioniert.

Jetzt habe ich das mal über Lan getestet, und bei dem Client Zuckt es, wenn die Karten bewegt werden und Lokal auf einem Rechner funktioniert es fließend.

Hier ist mal ein teil von meinem Code, wie ich die Daten von den Karten zum Clienten Sende:
BlitzMax: [AUSKLAPPEN]
For Local C:TCardStapel = EachIn CardStapelList
SetColor 200,200,200
SetImageHandle(card_image, ImageWidth(card_image)/2, ImageHeight(card_image)/2)
DrawImage card_image,C.X,C.Y-72,C.Frames
If C.Bedeckt = 1 Then DrawImage card_image,C.X,C.Y-72,52

If isServer = 1 Then
If C.Move = 1 Then
C.DistX = C.X - C.ZielX
C.X = C.X - C.DistX/20
C.DistY = C.Y - C.ZielY
C.Y = C.Y - C.DistY/20
If (C.DistX <= 10.1 And C.DistX >= -10.1) And (C.DistY <= 10.1 And C.DistY >= -10.1) Then
C.Move = 0
EndIf
For Client = EachIn Clients
Client.WriteByte(1)
Client.WriteByte(SpielerNr)
Client.WriteByte(C.Nr) '<< Zum identifizieren der Karte
Client.WriteByte(C.Frames)
Client.WriteByte(C.Wert)
Client.WriteFloat(C.X)
Client.WriteFloat(C.Y)
Client.WriteFloat(C.DistX)
Client.WriteFloat(C.DistY)
Client.WriteFloat(C.ZielX)
Client.WriteFloat(C.ZielY)
Client.WriteByte(C.Move)
Client.WriteByte(C.Nr)
Client.WriteByte(C.SpielerNr)
Client.WriteByte(C.CardID)
Client.WriteByte(Len(C.Karte))
Client.WriteString(C.Karte)
Client.WriteByte(Len(C.Typ))
Client.WriteString(C.Typ)
While Client.SendMsg() ; Wend
Next
EndIf
EndIf
Next


und so lese ich die Daten aus, beim Client:
BlitzMax: [AUSKLAPPEN]
Case 1
SpielerNr = Client.ReadByte()
Local Nr:Byte = Client.ReadByte() '<< Zum identifizieren der Karte
For Local C:TCardStapel = EachIn CardStapelList
If C.Nr = Nr Then
C.Frames = Client.ReadByte()
C.Wert = Client.ReadByte()
C.X = Client.ReadFloat()
C.Y = Client.ReadFloat()
C.DistX = Client.ReadFloat()
C.DistY = Client.ReadFloat()
C.ZielX = Client.ReadFloat()
C.ZielY = Client.ReadFloat()
C.Move = Client.ReadByte()
C.Nr = Client.ReadByte()
C.SpielerNr = Client.ReadByte()
C.CardID = Client.ReadByte()
Local l:Byte = Client.ReadByte()
C.Karte = Client.ReadString(l)
l = Client.ReadByte()
C.Typ = Client.ReadString(l)
EndIf
Next


Woran könnte das Problem denn liegen?

Ich bedanke mich schonmal im Voraus.

MfG
AMD Athlon(tm) II X2 250, 8 GB DDR, MSI MSI 770-C45, GeForce GTS 250

Tankbuster

BeitragFr, März 09, 2012 3:10
Antworten mit Zitat
Benutzer-Profile anzeigen
2 Stichwörter: Port-Forwarding und Hole-Punching.

Das erste dreht sich um die Router-Konfiguration beim Server. Ports müssen freigegeben werden, und zum richtigen PC weitergeleitet werden, ect...
Das zweite ist eine logische Möglichkeit, eine Firewall zu umgehen, damit die Spieler ihre Ports nicht manuell "forwarden" müssen.
Twitter
Download Jewel Snake!
Windows|Android
 

bruce85

BeitragFr, März 09, 2012 19:06
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich danke Dir.
Wie verwendet man eigentlich Hole-Punching in BlitzMax?

Ich hab mich mal bei Wiki mehr darüber informiert und komme leider nicht ganz klar damit, wie ich das ambesten hinbekommen könnte.
Ich wäre euch sehr dankbar, wenn mir jemand einen ansatz Posten könnt, wie man das ambesten aufbaut in BlitzMax.

MfG
AMD Athlon(tm) II X2 250, 8 GB DDR, MSI MSI 770-C45, GeForce GTS 250

Tankbuster

BeitragSa, März 10, 2012 4:21
Antworten mit Zitat
Benutzer-Profile anzeigen
Also.... ohne Portforwarding (und das will man dem Spieler ja ersparen), werden Nachrichten von außen, die an deinen Router kommen, einfach geblockt. Aus Sicherheitsgründen.
Nachrichten können aber aus dem Netzwerk des Routers ins Internet geschickt werden.

Wenn du von deinem PC nun TCP oder UDP Pakete von Port 1234 and die IP 11.11.11.11 und den Port 9999 schickst, dann erkennt dein Router das. Es wird gespeichert:

Port 1234 von PC1 (dein PC) des Netzwerkes versendet eine Nachricht an IP 11.11.11.11 auf Port 9999

Wenn dir nun die IP 11.11.11.11 eine Antwort von Port 9999 an Port 1234 sendet, dann weiß dein Router die Nachricht weiterzuleiten. Und er wird sie nicht blocken, da der Sender ja vorher "angeschrieben" wurde, und das nun die Antwort sein wird.

Willst du eine Peer-to-Peer connection ohne zentralen Server aufbauen, müssen alle Clients die genaue Adresse (IP und Port) des anderen kennen. Bei zwei ist das noch relativ einfach.
(in so einem Fall ist es am einfachsten, wenn alle Clients einen festgelegten Port benutzen)


gehen wir mal davon aus, beide Clients benutzen den selben Port:

Client 1 verschickt eine Nachricht "Hallo" and Client 2.
Die Nachricht wird von der Firewall von Client 2 geblockt. (Es ist in diesem Fall einfach eine Nachricht von außen, die aus sicherheitsgründen geblockt wird)

Client 2 sendet nun ein "Hallo" an Client 1.
Der Router von Client 1 wird diese Nachricht nicht blocken, weil ja zuvor Client 1 an Client 2 geschrieben hat, und Client 2 somit eine "seriöse" Adresse ist.

Daraufhin sendet Client 1 nochmals ein "Hallo".
Diesmal wird es nicht von der Firewall geblockt, und Client 2 empfängt die Nachricht ebenfalls.


Folglich muss man bei peer-to-peer Programmen am Anfang soetwas wie einen kleinen "Nachrichten Spam" erzeugen.

Client 1 sendet solange an Client 2, bis Client 2 eine Antwort gibt.
Und Client 2 sendet solange an Client 1, bis dieser wiederrum eine Antwort gibt.

Jetzt steht die Verbindung, und kann genutzt werden.



Bei einem zentralen Server sieht das ähnlich aus, allerdings kann man dort mit dynamischen Ports arbeiten, wenn der Server Portforwarding betreibt. So funktionieren praktisch alle Onlinespiele.

Dort speichert der Server die Ports und Adressen der einzelnen Clients, und kommuniziert entweder direkt mit dem Client, oder kann dem Client die Adressen und Ports der anderen Clients übermitteln, woraufhin dieser eine peer-to-peer verbindung wie oben beschrieben aufbauen kann.


MFG: Tank
Twitter
Download Jewel Snake!
Windows|Android
 

bruce85

BeitragSa, März 10, 2012 19:07
Antworten mit Zitat
Benutzer-Profile anzeigen
Vielen Dank für die antwort.

Ich werde mich damit mal auseinandersetzen und kucken, was ich machen kann.

MfG
AMD Athlon(tm) II X2 250, 8 GB DDR, MSI MSI 770-C45, GeForce GTS 250
 

bruce85

BeitragSo, März 11, 2012 0:21
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo nochmal,
ich habe testhalber mal bei meinem Roter den Port freigeschaltet vom Server und vom Client und habe mal alle Firewalls deaktiviert, leider hängt sich das Spiel trotzdem ab und zu auf, bei dem Client und es zuckt auch bei dem Client, wenn die Daten übertragen werden.

Locak auf einem Rechner funktioniert alles fließend, nur nicht übers Netzwerk oder Internet.

Liegt es Vielleicht dadran, dass ich es über TCP sende bzw. empfange und nicht über UDP?
Weil für Spiele ist ja eigentlich UDP ambesten geeignet.

Danke schonmal.

MfG
AMD Athlon(tm) II X2 250, 8 GB DDR, MSI MSI 770-C45, GeForce GTS 250
 

bruce85

BeitragMo, März 19, 2012 4:44
Antworten mit Zitat
Benutzer-Profile anzeigen
Hat denn niemand ne lösung für mein Problem?

Das Problem ist, das es Local auf einem Rechner fehlerfrei funktioniert, nur nicht übers Internet, obwohl die gewählte Ports frei sind.

Wenn ich das Spiel übers Internet Teste, dann bleibt es an einer bestimmten stelle hängen, bei den Clienten.
Die Clienten können fehlerfrei zum Server Verbinden und nachrichten austauschen u.s.w.
Aber sobald das Spiel gestartet wird, bleibt es an einer bestimmten Stelle hängen, wenn die Karten verteilt werden.
Der Server verteilt ja die Karten und sendet dann zu den Clienten die Positionen der Karten, das die Clienten ja auch mit bekommen, das die Karten verteilt werden und genau hier mitten drin, hängt sich das Spiel ab und zu bei den Clienten auf.
Bei den Clienten zuckt es auch, wenn die Karten verteilt werden, deshalb vermute ich, das ich die Daten der Karte nicht richtig zu den Clienten schicke.

Hier mal der Code, die Karten werden flüßig zu den Spielern verteilt und gleichzeitig sende ich dann die Positionen der Karten zu den Clienten:
BlitzMax: [AUSKLAPPEN]
'###### Den Kartenstapel zeichnen... ######
For Local C:TCardStapel = EachIn CardStapelList
SetColor 200,200,200

SetImageHandle(card_image, ImageWidth(card_image)/2, ImageHeight(card_image)/2)
DrawImage card_image,C.X,C.Y-72,C.Frames
If C.Bedeckt = 1 Then DrawImage card_image,C.X,C.Y-72,52

If isServer = 1 Then
If C.Move = 1 Then
C.DistX = C.X - C.ZielX
C.X = C.X - C.DistX/20
C.DistY = C.Y - C.ZielY
C.Y = C.Y - C.DistY/20
If (C.DistX <= 10.1 And C.DistX >= -10.1) And (C.DistY <= 10.1 And C.DistY >= -10.1) Then
C.Move = 0
C.CardDelete = 1
Spieler[C.SpielerNr-1].Card = New TCard
Spieler[C.SpielerNr-1].Card.Frames = C.Frames
Spieler[C.SpielerNr-1].Card.Karte = C.Karte
Spieler[C.SpielerNr-1].Card.Typ = C.Typ
Spieler[C.SpielerNr-1].Card.Wert = C.Wert
Spieler[C.SpielerNr-1].Card.SpielerNr = C.SpielerNr
Spieler[C.SpielerNr-1].CardList.AddLast(Spieler[C.SpielerNr-1].Card)
Spieler[C.SpielerNr-1].CardAnz = Spieler[C.SpielerNr-1].CardAnz + 1
Spieler[C.SpielerNr-1].Card.Nr = Spieler[C.SpielerNr-1].CardAnz

For Client = EachIn Clients
Client.WriteByte(11)
Client.WriteByte(C.SpielerNr)
While Client.SendMsg() ; Wend
Next
EndIf

For Client = EachIn Clients
Client.WriteByte(1)
Client.WriteByte(CardStapelAnz)
Client.WriteByte(ZugAktiv)
Client.WriteByte(AusteilenAktiv)
Client.WriteByte(SpielerNr)
Client.WriteByte(C.Nr) '<< Zum identifizieren der Karte
Client.WriteByte(C.Frames)
Client.WriteByte(C.Wert)
Client.WriteFloat(C.X)
Client.WriteFloat(C.Y)
Client.WriteFloat(C.DistX)
Client.WriteFloat(C.DistY)
Client.WriteFloat(C.ZielX)
Client.WriteFloat(C.ZielY)
Client.WriteByte(C.Move)
Client.WriteByte(C.Nr)
Client.WriteByte(C.SpielerNr)
Client.WriteByte(C.CardID)
Client.WriteByte(Len(C.Karte))
Client.WriteString(C.Karte)
Client.WriteByte(Len(C.Typ))
Client.WriteString(C.Typ)
While Client.SendMsg() ; Wend
Next
EndIf
EndIf
Next
'##########################################################################################################


und hier lese ich dann die Daten der Karte aus:
BlitzMax: [AUSKLAPPEN]
Case 1
CardStapelAnz = Client.ReadByte()
ZugAktiv = Client.ReadByte()
AusteilenAktiv = Client.ReadByte()
SpielerNr = Client.ReadByte()
Local Nr:Byte = Client.ReadByte() '<< Zum identifizieren der Karte
For Local C:TCardStapel = EachIn CardStapelList
If C.Nr = Nr Then
C.Frames = Client.ReadByte()
C.Wert = Client.ReadByte()
C.X = Client.ReadFloat()
C.Y = Client.ReadFloat()
C.DistX = Client.ReadFloat()
C.DistY = Client.ReadFloat()
C.ZielX = Client.ReadFloat()
C.ZielY = Client.ReadFloat()
C.Move = Client.ReadByte()
C.Nr = Client.ReadByte()
C.SpielerNr = Client.ReadByte()
C.CardID = Client.ReadByte()
Local l:Byte = Client.ReadByte()
C.Karte = Client.ReadString(l)
l = Client.ReadByte()
C.Typ = Client.ReadString(l)
EndIf
Next


Ich bedanke mich schonmal im Voraus.

Edit: Liegt es Vielleicht an der TCP Verbindung?
TCP sollte ja für dieses Spiel ausreichen oder?

MfG
AMD Athlon(tm) II X2 250, 8 GB DDR, MSI MSI 770-C45, GeForce GTS 250

Xeres

Moderator

BeitragMo, März 19, 2012 12:19
Antworten mit Zitat
Benutzer-Profile anzeigen
Wenn dir jemand helfen könnte oder wollte, würde er es tun.
Mehrfachposts und push führt hier nur zum close - benutze den Editbutton und ansonsten übe dich in Geduld.
Betrachte dies als die letzte, freundliche Erinnerung.
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)

ZEVS

BeitragMo, März 19, 2012 18:02
Antworten mit Zitat
Benutzer-Profile anzeigen
Ein allgemeiner Hinweis zum Debuggen von Internetverbindungen: Schau' dir doch mal von einer unabhängigen Quelle an, wo das Problem auftritt indem du dir anschaust, was überhaupt durchs Netzwerk kommt. Ich verwende momentan WireShark, damit kann man auch bei binären Protokollen ziemlich genau feststellen, ob fehlerhafte Daten gesendet werden und ggf. was falsch ist.
Nur so als allgemeiner Tipp.

ZEVS

Tankbuster

BeitragDi, März 20, 2012 4:23
Antworten mit Zitat
Benutzer-Profile anzeigen
Was ist denn CardStapelAnz ? Wenn das eine globale Variable ist, wird sie nämlich überschrieben, und wenn das beim Server passiert, wäre es eventuell sehr schlecht.... dazu kann man ohne mehr Code aber nichts sagen.....

Es könnte ebenfalls daran liegen, dass du jedem Spieler für jeden Kartenstapel erneut Byte 11 sendest. Ich weiß ja nicht, wie du es gelöst hast, aber eventuell liegt da auch der Fehler... jeder Spieler sollte es nur einmal oder garnicht bekommen?

Code: [AUSKLAPPEN]
      
For Local C:TCardStapel = EachIn CardStapelList
[...]
         For Client = EachIn Clients
                  Client.WriteByte(11)
                  Client.WriteByte(C.SpielerNr)
                  While Client.SendMsg() ; Wend
         Next
[...]
Next


Ich möchte noch anmerken, dass die ganze Sache sehr komisch gehandhabt ist... du musst ja keinesfalls die Positionen der Karten in Realtime übermitteln. Du könntest per TCP einfach ein Byte schicken, das den Status einer Karte sendet. Der Client übernimmt dann die Positionsberechnung (Beispiel: Status = 1 bedeutet Karte wird gezogen, Status 0 = Karte ist im Stapel und Status 2 = Karte ist auf der Hand, ect)

Um es Cheatern schwer zu machen, solltest du auch nur die Karten an den Client senden, die dieser auf der Hand hat. Die Karten der anderen werden nur bei wirklichem Bedarf gesendet... nunja, das ist ehr eine Sicherheitsmaßnahme....
Twitter
Download Jewel Snake!
Windows|Android
 

bruce85

BeitragMo, März 26, 2012 2:55
Antworten mit Zitat
Benutzer-Profile anzeigen
Vielen Dank für die antworten.
Ich denke, dass ich das Problem gefunden habe...
Es werden einfach sehr viele Datenpakete pro Schleifendurchlauf gesendet und daher enstehen auch die Lags.
Ich hab mich einbisschen mehr über TCP hier im Forum informiert und habe gelesen, dass bei TCP das Problem besteht, dass Pakete zurückgehalten werden können und dadurch einfach künstliche Lags entstehen können.

Ich werde es einfach mal versuchen, das Problem mit UDP lösen.

MfG
AMD Athlon(tm) II X2 250, 8 GB DDR, MSI MSI 770-C45, GeForce GTS 250

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group