0
我建立一個客戶機/服務器應用程序來學習如何遊戲基於客戶機/服務器的作品,但應用程序似乎不能很好地工作,這裏是我的問題:如何正確構建客戶端/服務器應用程序?
- 爲什麼不能這樣應用程序可以」 t關閉客戶端應用程序時寫入「播放器XXX離開」
- 如何正確接收來自服務器的數據? (我想接收來自服務器的位置信息,以使其在客戶端)
這裏是全碼:
服務器:
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);
}
}
我*假設你的意思是「客戶/服務器」的「C/S」?這部分問題嚴重隱含,但從未明確闡述。 –
你的問題太廣泛了。對最簡單部分的簡短回答:您無法檢查客戶端狀態,因爲您的代碼卡在'AcceptTcpClient()'調用中。你會看到,如果你使用調試器來看看代碼在做什麼。解決這類問題的常用方法是編寫異步代碼,以便在網絡I/O事件發生時響應,而不會阻止任何一個線程響應。我在最近發佈的[這個答案](https://stackoverflow.com/a/44942011)中有一個例子。 –