Netzwerkfähiges Spiel



  • Hallo,

    ich würde gern ein netzwerkfähiges Handy Spiel programieren. Also total einfaches. Ohne Server. Nur 2 Clients. Der eine denkt sich eine Zahl aus, der andere muss raten. ClientA sendet String "Welche Zahl hab ich mir ausgedacht". ClientB sendet eine Zahl. ClientA sendet "Zahl war richtig oder nicht".

    Nun meine Frage wie bau ich die Verbindung auf.

    Kann das mal einer skizzieren. Client A gibt seine IP ein und Client B gibt sein IP ein . Dann bau ich über Socket die Verbindung auf. Geht das so ??

    Hat jemand nen passenden Link dafür ...

    Wie ist das wenn beide Spieler nach aussen die selbe IP haben. Beide sitzen hinter einem Router. Kein Problem da beide anderen Port haben oder..



  • für so einfache Zwecke kannst du dir UDP ansehen.
    Dabei hast du S (Sender) und E (Empfänger).
    Bei S gibst du die IP vom E ein. E lauscht auf einem Port (nichts anderes als eine Zahl) auf einkommende Pakete.
    Nun schickt S ein Paket an E, genauer gesagt an IP:Port. Dieser empfängt das Paket und hat nun Zugriff auf dieses Paket. Wenn du z.B. 4 Byte sendest, welche die Zahl codieren, so nimmst du die 4 Byte und verwendest sie dann eben für deine Zwecke.

    UDP über Sockets ist recht einfach, ähnlich wie Filehandling.
    Siehe z.B. http://www.c-worker.ch/tuts/udp.php



  • Wozu sendest du einen String? Willst du ein Chatprogramm schreiben?

    Wenn die Spielregeln klar sind, dann genügt die Zahl.



  • Peer-to-Peer über das Internet ist in der Regel ohne einen weiteren Server nicht möglich. Du musst entweder einen Relay-Server zwischenschalten, Ports auf den Routern weiterleiten (falls verfügbar z.B. über UPnP) oder NAT Traversal (Hole Punching) bemühen. Nur die zweite Variante braucht keinen weiteren Server.



  • Das sind mehrere Fragen in einem.
    Zur Architecktur:
    Du musst trotzdem einen der Spieler zum "Server" machen, dh der auf eingehende Verbindungen wartet.
    Dafür brauchts Du dann auch nur die IP Adresse von diesem auf dem anderen Device. (und nicht beide).
    Also zB A denkt sich Zahl aus und hostet die Partie, dh ist Server und wartet auf die Verbindung.
    B verbindet zu A (muss dessen Adresse kennen).
    Anschliessend sendet B seine Ratezahl und A antwortet auf dem *gleichen* Kanal zurück - der ist nämlich dann in beide Richtungen verfügbar.
    (Und nimm TCP , nicht UDP wie jemand vorgeschlagen hat. TCP ist zwar das komplexere Protokoll, aber das ist weil es Dir Arbeit abnimmt!)

    Zur Topologie:
    Den Server zu erreichen ist im LAN kein Problem. (ausser evtl Software Firewalls auf dem Gerät).
    Im Internet muss der Serverport allerdings sichtbar sein, i.a. über Port-Weiterleitung vom Internet ins LAN, wie es Jodocus angedeutet hat.



  • Das Spiel soll auf meinen beiden Android Smartphones laufen. Wie ist da jetzt der Ablauf.

    Ich biete eine GUI an in der beide die IP des Gegners eingeben müssen oder.
    Ich muss im Android manifest die Permissions setzen. Da auf beiden Smartphones die gleiche App läuft würden auch beide den Server dabei haben.
    Kennt einer nen guten Link wo vielleicht schon mal einer sowas implementiert hat...



  • network Tic Tac Toe game. Das wirds doch bestimmt geben...
    Wie meisten Beispiele wo ich gefunden hab, da gibts halt nen extra Server unabhängig von meinen beiden Smartphones. Glaubt ihr wirklich dass das ohne extra Server geht ?? Ich hab nur meine beiden Smartphones. Mehr hab ich nicht...

    hm. Also ich stell mir das so vor.

    Es gibt einen Button "Start Game" , dann ist dieses smartphone der Server und Client
    und es gibt einen Button "Join Game" , dieses Smartphone ist dann nur Client und dieser muss dann die Ip des Servers eingeben und seine IP an den Server schicken...

    Das sollte doch problemlos möglich sein, dass eine App Client und Server gleichzeitig ist...



  • Mach's doch wie @scrontch gesagt hat.

    Und vergiss mal für einen Moment "Server" und "Client". Im Endeffekt brauchst du auf jedem Gerät ein Socket, also Netzwerk-Endpunkt, welches die Verbindung zw. den Geräten darstellt.

    "Server" sagt man, wenn ein sogenanntes "listening"-Socket erstellt wird. Dieses wartet auf Verbindungen von außen. Wenn sich wer verbindet, erhältst du vom OS ein neues Socket, das stellt dann die Verbindung dar.
    "Client" sagt man, wenn ein Socket erstellt wird, mit dem man sich dann zu einer bestimmten Adresse verbindet. Dieses Socket stellt dann die Verbindung dar.

    Du kannst auf beiden Seiten den gleichen Code haben, nur auf einer Seite machst du eben listen(), accept() etc. (Server-style) und auf der anderen nur connect() (Client-style).

    Die IP wird nicht wo hingeschickt, die übergibst du an connect().

    Such einfach mal nach ganz simplen Tutorials, je nachdem welches socket API du verwenden willst (berkeley, windows-varianten (WSA...) oder sonstige libs oder frameworks).

    Wenn beide Geräte per Mobilfunk am Internet sind, brauchst du wahrscheinlich nichts weiter zu tun, da du dann zwei public IPs hast (Wobei ich schon davon gehört habe, dass Provider mehreren Kunden die gleiche IP geben, dann müsstest du wohl mal den Support anrufen. Stichwort: carrier-grade NAT).
    Ebenso, wenn beide Geräte zB. per WLAN im gleichen Netz sind.



  • Hi schrieb:

    Wenn beide Geräte per Mobilfunk am Internet sind, brauchst du wahrscheinlich nichts weiter zu tun, da du dann zwei public IPs hast (Wobei ich schon davon gehört habe, dass Provider mehreren Kunden die gleiche IP geben, dann müsstest du wohl mal den Support anrufen. Stichwort: carrier-grade NAT).

    Dann wird's erst richtig kompliziert meinst du. CGNs sind auch noch symmetrisch, d.h. NAT-Traversal wird sehr schwer.



  • Jodocus schrieb:

    Hi schrieb:

    Wenn beide Geräte per Mobilfunk am Internet sind, brauchst du wahrscheinlich nichts weiter zu tun, da du dann zwei public IPs hast (Wobei ich schon davon gehört habe, dass Provider mehreren Kunden die gleiche IP geben, dann müsstest du wohl mal den Support anrufen. Stichwort: carrier-grade NAT).

    Dann wird's erst richtig kompliziert meinst du. CGNs sind auch noch symmetrisch, d.h. NAT-Traversal wird sehr schwer.

    Ein Kumpel aus Tschechien hatte mal das Problem, als er einen Gameserver hosten wollte. Sein Provider hat ihm auf Anfrage tatsächlich eine public IP zugewiesen.



  • Ich schreibe grad den client und hab da so ein kleines codestück aus dem Internet etwas angepasst. Aus irgendeinem Grund kann mein Client nur ein einziges Mal senden. Und das trotz der while Schleife. Ich versteh das nicht.
    clientSocket.close() hab ich auch auskommentiert.

    public class Client {
    
    	public void start() throws Exception
    	{
    		  String sentence;
    		  String modifiedSentence;
    		  BufferedReader inFromUser = new BufferedReader( new InputStreamReader(System.in));
    		  Socket clientSocket = new Socket("localhost", 6770);
    		  DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
    		  BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
    		  while(true)
    		  {
    			  System.out.println("Client starts");
    			  sentence = inFromUser.readLine();
    			  outToServer.writeBytes(sentence + '\n');
    			  modifiedSentence = inFromServer.readLine();
    			  System.out.println("FROM SERVER: " + modifiedSentence + "\n");
    			  //clientSocket.close();
    		  }	  
    	}
    }
    


  • Ihh, C# 🙂

    Äh, naja, readLine() wartet wohl auf Datenempfang.

    Empfängt sentence.
    Sendet sentence + Zeilenumbruch.
    Empfängt modSentence.
    Gibt aus modSentence.

    Damit erneut gesendet wird, muss also erst mal was empfangen werden. readLine() ist nämlich bestimmt ein blocking call.



  • Das ist java. Und klar nach dem ersten Senden des Clients , kommt natürlich was vom Server zurück. Wenn ich dann wieder senden möchte, dann gehts nicht...



  • Doppel-Ihh, Java 🤡

    Dann zeig mal deinen Code.



  • Das ist mein Code für den Client. Am Server liegts nicht. Wenn ich den Client wieder neu starte dann kommt auch wieder was vom Server zurück.



  • Peter_mueller12 schrieb:

    Am Server liegts nicht.

    Warum bist du dir da so sicher?
    Bei diesem Code muss der Server erst mal was senden, damit der Client was zurücksendet.



  • Ich tippe mal darauf, dass der Server kein Newline sendet.



  • Im Zweifel wer was sendet einfach mit Wireshark gucken.



  • Das ist der Server Code . Und ja dieses new Line das macht wohl Probleme. Warum eigentlich frag ich mich da. Aber das löst das Problem trotzdem noch nicht..

    String clientSentence="";
            String capitalizedSentence;
            ServerSocket welcomeSocket = new ServerSocket(6770);
    
            while(true)
            {
               Socket connectionSocket = welcomeSocket.accept();
               BufferedReader inFromClient =
                  new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
               DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
               clientSentence = clientSentence + inFromClient.readLine();
               System.out.println("Received: " + clientSentence);
               capitalizedSentence = clientSentence + '\n';
               System.out.println(capitalizedSentence);
               outToClient.writeBytes(capitalizedSentence); 
            }
    


  • Weißt du überhaupt, was der Code macht? Scheinbar nicht.

    Dieses .accept() ist bestimmt auch ein blocking call. Somit wartet der Server in jedem Schleifendurchgang immer erst auf eine neue Verbindung.
    Die kommt aber nur dann zustande, wenn du den Client (neu) startest.
    Also ein Client Neustart (connect->accept), ein Server send.

    Doofer Code. Doofes copy & paste.

    Guck dir an, wie man mit Sockets umgeht.


Log in to reply