2017-08-14 183 views
0

我建立一個客戶機/服務器應用程序來學習如何遊戲基於客戶機/服務器的作品,但應用程序似乎不能很好地工作,這裏是我的問題:如何正確構建客戶端/服務器應用程序?

  1. 爲什麼不能這樣應用程序可以」 t關閉客戶端應用程序時寫入「播放器XXX離開」
  2. 如何正確接收來自服務器的數據? (我想接收來自服務器的位置信息,以使其在客戶端)

這裏是全碼:

服務器:

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] = "*"; 
      } 
     } 
    } 
} 

客戶:

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

我*假設你的意思是「客戶/服務器」的「C/S」?這部分問題嚴重隱含,但從未明確闡述。 –

+1

你的問題太廣泛了。對最簡單部分的簡短回答:您無法檢查客戶端狀態,因爲您的代碼卡在'AcceptTcpClient()'調用中。你會看到,如果你使用調試器來看看代碼在做什麼。解決這類問題的常用方法是編寫異步代碼,以便在網絡I/O事件發生時響應,而不會阻止任何一個線程響應。我在最近發佈的[這個答案](https://stackoverflow.com/a/44942011)中有一個例子。 –

回答

0

解決方案:

對於傳輸客戶端運動w ith服務器,你會想要使用UDP的速度。這是經常在遊戲中傳輸數據的最有效方式。

至於你的其他問題,它最有可能不知道客戶端,可能你的連接沒有被正確關閉,因此連接必須超時才能被識別爲關閉。

相關問題