Flo*_*ian 0 c# design-patterns tcp tcplistener tcpclient
我想知道如何写一个"好"的游戏服务器.我有一些想法,但我从来没有制作过服务器,我不想最终编写brainfuck代码.
我知道如何处理TCP-Connections等但我的问题是如何在服务器和客户端之间进行通信.
例如:我写了一个类似TicTacTow的游戏.现在用户点击了一个单元格,我想告诉该服务器.服务器应验证用户是否可以单击该单元并告知客户端.如果服务器说是; 您可以单击客户端将其显示为"X".
现在我的问题:我如何告诉服务器我想要点击该字段.我在这里遇到了另一个问题,他们最终使用了命令模式.但如果我理解正确,我将不得不创建一个实现接口的命令.我序列化该命令的一个实例并将其发送到服务器.服务器执行命令.但我必须解决主要问题:
所以我正在寻找更好的东西.我只想为我的客户端和服务器提供一个简单易用的架构.有什么好的模式吗?
哦,还有一个问题:你会使用序列化器吗?或者你自己编码数据?
是什么让你直接使用对象的序列化?对于游戏服务器而言,这将是一件非常糟糕的事情,因为它很慢,可能容易中断(特别是如果你有一个复杂的对象图来序列化),而且通常是hackish.解决方案是从头开始设计和实现您自己的游戏通信协议 - 幸运的是,它很容易.
序列化主要在无聊的业务应用程序和数据层中完成,其目标是通常在异构系统之间轻松传输数据,这就是经常使用基于XML的序列化的原因.这些要求不适用于游戏.
请注意,序列化对象仅序列化数据成员,它不会序列化方法.因此,您对恶意代码被发送的恐惧是没有根据的.
无论如何,服务器设计的第一条规则是永远不要信任客户端 - 这意味着游戏服务器需要在内存中维护当前游戏状态的副本,并将游戏规则应用于从客户端发送的每个游戏移动消息.
从鸟瞰角度来看,这就是我设计你的井字系统的方法:
因为对游戏状态的更改是事件驱动的并且它是基于回合的,所以基于动词和参数的协议最有效.我会有以下动词,假设这是一个严格的2人游戏(使用2个客户端和服务器)
客户端到服务器JOIN
READY
MOVE (x, y)
QUIT
Run Code Online (Sandbox Code Playgroud)
服务器到客户端
JOINED
ISREADY
MOVED (player, x, y)
DENIED (reason)
LEFT
Run Code Online (Sandbox Code Playgroud)
客户端到服务器的动词应该是不言自明的.您会注意到服务器到客户端谓词是原始客户端到服务器消息的代理版本,但MOVED包含移动的玩家的ID,并且还包含DENIED以通知客户其移动被拒绝.LEFT动词用于表示其他玩家已退出.
这是一个假设的Tic-tac-toe服务器的不完整的伪代码实现.我编写的代码只涉及应用程序的网络层,围绕井字游戏规则和移动的所有实际逻辑都包含在TicTacToeBoard类中,这里不再描述,但实现起来应该是微不足道的.
服务器逻辑发生在单个线程中,但必要时,用于复用来自网络的传入消息的逻辑将需要在不同的线程上发生.这里不详述,它是抽象的背后掩盖WaitForAndGetConnection,GetLastIncomingMessage和SendMessage方法.
// Ready-room state
connection1 = WaitForAndGetConnection();
connection2 = WaitForAndGetConnection();
SendMessage( connection1, "JOINED" ); // inform player 1 that another player joined
p1Ready = false, p2Ready = false;
while(message = GetLastIncomingMessage() && !p1Ready && !p2Ready) {
if( message.From == connection1 && message.Verb == "READY" ) p1Ready = true;
if( message.From == connection2 && message.Verb == "READY" ) p2Ready = true;
}
SendMessage( connection1, "ISREADY" ); // inform the players the game has started
SendMessage( connection2, "ISREADY" ); // inform the players the game has started
// Game playing state
TicTacToeBoard board = new TicTacToeBoard(); // this class represents the game state and game rules
p1Move = true; // indicates whose turn it is to move
while(message = GetLastIncomingMessage()) {
if( message.Verb == "MOVE" ) {
if( p1Move && message.From == connection1 ) {
if( board.Player1Move( message.X, message.Y ) ) {
SendMessage( connection1, "MOVED (1, " + message.X + "," + message.Y + " )");
SendMessage( connection2, "MOVED (1, " + message.X + "," + message.Y + " )");
p1Move = false;
} else {
SendMessage( message.From, "DENIED \"Disallowed move.\".");
}
} else if( !p1Move && message.From == connection2 ) {
if( board.Player2Move( message.X, message.Y ) ) {
SendMessage( connection1, "MOVED (2, " + message.X + "," + message.Y + " )");
SendMessage( connection2, "MOVED (2, " + message.X + "," + message.Y + " )");
p1Move = true;
} else {
SendMessage( message.From, "DENIED \"Disallowed move.\".");
}
} else {
SendMessage( message.From, "DENIED \"It isn't your turn to move\".");
}
if( board.IsEnded ) {
// handle game-over...
}
} else if( message.Verb == ... // handle all of the other verbs, like QUIT
}
}
Run Code Online (Sandbox Code Playgroud)
HTH.
| 归档时间: |
|
| 查看次数: |
1939 次 |
| 最近记录: |