2017-08-14 5 views
0

Ich bin den Aufbau einer Client/Server-Anwendung Spiel zu lernen, wie auf Client/Server-Arbeiten basieren, aber die Anwendung scheint kann auch nicht funktionieren, hier sind meine Fragen:Wie erstellt man eine Client/Server-Anwendung richtig?

  1. Warum kann diese App kann‘ t schreibe "Player XXX leaves" wenn ich die Client-Anwendung schließe
  2. Wie bekomme ich Daten vom Server richtig? (Ich möchte eine Position Infos von Server erhalten sie in Client zu machen)

hier ist der vollständige Code:

Server:

public class ServerApp 
{ 
    public class Point 
    { 
     public int x; 
     public int y; 
    } 

    TcpListener listener; 
    List<Player> players; 

    string[,] data = new string[20, 40]; 

    public ServerApp() 
    { 
     players = new List<Player>(); 
    } 

    void PlayerJoin(TcpClient client) 
    { 
     lock (data) 
     { 
      if (data[0, 0] == "*") 
      { 
       data[0, 0] = "O"; 
       Player player = new Player(); 
       player.Entity = "O"; 
       player.Location = new Vector2(0,0); 
       player.Client = client; 
       players.Add(player); 
      } 
      else if (data[0, 39] == "*") 
      { 
       data[0, 40] = "P"; 
       Player player = new Player(); 
       player.Entity = "P"; 
       player.Location = new Vector2(0, 0); 
       player.Client = client; 
       players.Add(player); 
      } 
      else if (data[19, 0] == "*") 
      { 
       data[20, 0] = "I"; 
       Player player = new Player(); 
       player.Entity = "I"; 
       player.Location = new Vector2(0, 0); 
       player.Client = client; 
       players.Add(player); 
      } 
      else if (data[19, 39] == "*") 
      { 
       data[20, 40] = "U"; 
       Player player = new Player(); 
       player.Entity = "U"; 
       player.Location = new Vector2(0, 0); 
       player.Client = client; 
       players.Add(player); 
      } 
     } 
    } 

    void InitData(ref string[,] data) 
    { 
     for (int i = 0; i < 20; i++) 
     { 
      for (int j = 0; j < 40; j++) 
      { 
       if (i != 0 && i != 19) 
       { 
        if (j != 0 && j != 39) 
        { 
         data[i, j] = " "; 
        } 
        else 
        { 
         data[i, j] = "*"; 
        } 
       } 
       else 
       { 
        data[i, j] = "*"; 
       } 
      } 
     } 
    } 

    void InitServer() 
    { 
     listener = new TcpListener(new IPAddress(new byte[] { 127, 0, 0, 1 }), 6666); 
     listener.Start(); 
    } 

    void SyncDataToAllClient() 
    { 
     foreach (var player in players) 
     { 
      StreamWriter sw = new StreamWriter(player.Client.GetStream()); 
      int[] pos = new int[2]; 
      pos[0] = player.Location.x; 
      pos[1] = player.Location.y; 
      sw.Write(pos[0]); 
      sw.Write(pos[1]); 
      sw.Close(); 
     } 
    } 

    public void Run() 
    { 
     InitServer(); 
     InitData(ref data); 

     while (true) 
     { 
      if(listener.pending()) 
      { 
      var myclient = listener.AcceptTcpClient(); 
      if (myclient != null) 
      { 
       Console.WriteLine(string.Format("Client from {0} connected!", ((IPEndPoint)myclient.Client.RemoteEndPoint).Address)); 
       PlayerJoin(myclient); 

       Thread.Sleep(1000 * 5); 

       StreamWriter sw = new StreamWriter(myclient.GetStream()); 
       sw.Write(data); 
      } 
      CheckClient(); 
      SyncDataToAllClient(); 
      } 
     } 
    } 

    private void CheckClient() 
    { 
     foreach (var p in players) 
     { 
      if (!p.Client.Connected) 
      { 
       Console.WriteLine("Player {0} leave!", ((IPEndPoint)p.Client.Client.RemoteEndPoint).Address); 
       players.Remove(p); 
       data[p.Location.y, p.Location.x] = "*"; 
      } 
     } 
    } 
} 

Auftraggeber:

public class ClientApp 
{ 
    TcpClient client; 

    string[,] data = new string[20, 40]; 
    bool quit; 
    public void Run() 
    { 
     EstablishConntionToServer(); 
     InitData(ref data); 
     while (!quit) 
     { 
      SyncDataFromServer(ref data); 
      PrintData(data); 
     } 
    } 

    void EstablishConntionToServer() 
    { 
     client = new TcpClient(); 
     client.Connect(new IPAddress(new byte[] { 127, 0, 0, 1 }), 6666); 
    } 

    void SyncDataFromServer(ref string[,] data) 
    { 
     Stream s = client.GetStream(); 
     char[] buffer=new char[1]; 
     StreamReader sr = new StreamReader(s); 
     sr.Read(buffer,0,1); 
    } 

    void InitData(ref string[,] data) 
    { 
     for (int i = 0; i < 20; i++) 
     { 
      for (int j = 0; j < 40; j++) 
      { 
       //data[i, j] = "*"; 
       if (i != 0 && i != 19) 
       { 
        if (j != 0 && j != 39) 
        { 
         data[i, j] = " "; 
        } 
        else 
        { 
         data[i, j] = "*"; 
        } 
       } 
       else 
       { 
        data[i, j] = "*"; 
       } 
      } 
     } 
    } 

    void PrintData(string[,] data) 
    { 
     Console.Clear(); 
     for (int i = 0; i < 20; i++) 
     { 
      for (int j = 0; j < 40; j++) 
      { 
       Console.Write(data[i, j]); 
      } 
      Console.Write(Environment.NewLine); 
     } 

     System.Threading.Thread.Sleep(500); 
    } 
} 
+0

Ich * vermute * mit "C/S" meinst du "Client/Server"? Es ist stark durch Teile Ihrer Frage impliziert, aber nie explizit ausgesprochen. –

+1

Ihre Frage ist viel zu breit. Die kurze Antwort auf den einfachsten Teil: Sie können den Client-Status nicht überprüfen, da Ihr Code beim 'AcceptTcpClient()' -Aufruf blockiert ist. Was Sie gesehen hätten, wenn Sie einen Debugger verwendet hätten, um zu sehen, was der Code macht. Der übliche Weg, um solche Probleme zu lösen, besteht darin, asynchronen Code zu schreiben, so dass Sie auf Netzwerk-E/A-Ereignisse reagieren können, ohne dass ein Thread reagiert. Ich habe ein Beispiel dafür in [dieser Antwort] (https://stackoverflow.com/a/44942011), das ich kürzlich gepostet habe. –

Antwort

0

Lösungen:

Für die Übertragung von Client-Bewegungen w Mit dem Server möchten Sie UDP für seine Geschwindigkeit verwenden. Es ist der effizienteste Weg, um Daten zu übertragen, die oft in Spielen benötigt werden.

Wie für Ihre andere Frage, es ist wahrscheinlich nicht bekannt, den Client verlassen, ist es möglich, Ihre Verbindung wurde nie richtig geschlossen und daher muss die Verbindung Zeit als geschlossen erkannt werden.