如何正确构建客户端/服务器应用程序?

时间:2017-08-14 10:22:49

标签: c# networking

我正在构建一个客户端/服务器应用程序,以了解基于客户端/服务器的游戏如何工作,但应用程序似乎无法正常工作,这是我的问题:

  1. 当我关闭客户端应用程序时,为什么这个应用程序无法写“Player XXX离开”
  2. 如何正确地从服务器接收数据? (我希望从服务器接收位置信息以在客户端中呈现它)
  3. 这是完整的代码:

    服务器:

    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);
        }
    }
    

1 个答案:

答案 0 :(得分:0)

解决方案:

要使用服务器传输客户端移动,您可能希望使用UDP来提高速度。这是经常在游戏中传输数据的最有效方式。

至于你的另一个问题,它很可能不知道客户端离开了,你的连接可能从未被正确关闭,因此连接必须超时被识别为关闭。