首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C# Gameserver架构

C# Gameserver架构
EN

Stack Overflow用户
提问于 2013-02-16 09:19:03
回答 1查看 2.4K关注 0票数 1

我想知道怎么写一个“好的”游戏玩家。我有一些想法,但我从来没有做过一个服务器,我不想以编写brainfuck代码而告终。

我知道如何处理TCP连接等等,但我的问题是如何在服务器和客户端之间进行通信。

举个例子:我写了一个类似TicTacTow的游戏。现在一个用户点击了一个单元格,我想告诉那个服务器。服务器应该验证用户是否可以单击该单元格并告诉客户端。如果服务器同意,您可以单击客户端将其显示为"X“。

现在,我的问题是:我如何确切地告诉服务器,我想单击该字段。我在这里遇到了另一个问题,他们最终使用了命令模式。但是,如果我正确理解它,我将不得不创建一个命令来实现一个接口。我序列化该命令的一个实例并将其发送到服务器。服务器执行命令。但我要指出的主要问题是:

  1. 如果命令将tictacto的单元格设置为X,我如何告诉服务器,他必须传递GameBoard,我需要将该单元格设置为X到接口ICommand的调用方法。
  2. 这不是很不安全吗?我的意思是,我可以编写一个命令,删除所有文件或停止服务器并将其发送到服务器。我不相信指挥模式是那么好的主意。

所以我在寻找更好的东西。我只想为我的客户端和服务器提供一个简单、可扩展的体系结构。有什么好的模式吗?

还有另一个问题:您是使用序列化程序还是自己对数据进行编码?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-02-16 09:42:01

是什么给了您直接使用对象序列化的想法?这对游戏服务器来说是一件非常糟糕的事情,因为它速度慢,容易崩溃(特别是当您有一个复杂的对象图要序列化时),而且通常都是恶意的。解决方案是从零开始设计和实现自己的游戏通信协议--幸运的是,这很容易。

序列化主要是在枯燥的业务应用程序和数据层中完成的,目的是方便地在异构系统之间传输数据,这就是为什么经常使用基于XML的序列化。这些要求不适用于游戏。

注意,序列化对象只序列化数据成员,而不序列化方法。所以你对恶意代码的担心是没有根据的。

无论如何,服务器设计的第一条规则是永远不要信任客户端--这意味着游戏服务器需要在内存中维护当前游戏状态的副本,并将游戏规则应用于从客户端发送的每个游戏移动消息。

从鸟瞰的角度来看,下面是我设计你的抽搐脚趾系统的方法:

协议

因为游戏状态的改变是事件驱动的,并且是基于转弯的,所以基于谓词和参数的协议效果最好。我将有以下动词,假设这是一个严格的两人游戏(使用两个客户端和一个服务器)

客户对服务器

代码语言:javascript
复制
JOIN
READY
MOVE (x, y)
QUIT

服务器对客户端

代码语言:javascript
复制
JOINED
ISREADY
MOVED (player, x, y)
DENIED (reason)
LEFTGAME (player)

客户机到服务器的动词应该是不言自明的。您将注意到服务器到客户端的谓词是原始客户端到服务器消息的代理版本,但移动的除外包含移动的播放机的ID,还包含拒绝通知客户的移动。LEFTGAME动词用来表示另一个玩家已经退出。

服务器

这是一个不完整的psuedo代码实现假设的Tic-tac服务器。我所编写的代码只涉及应用程序的网络层,所有围绕tic游戏规则和动作的实际逻辑都包含在TicTacToeBoard类中,而不是在这里描述,但是实现起来应该很简单。

服务器逻辑发生在单个线程中,如果在Task中使用现代的.NET /async IO API,那么用于解复用传入消息的逻辑可以很容易地在单个线程中完成,否则使用单线程/远程连接也可以快速而简单地处理它(2人游戏不需要担心扩展--但这不会很好地扩展到数百名玩家)。(这里没有详细介绍处理这些远程连接的代码,它隐藏在抽象的WaitForAndGetConnectionGetLastIncomingMessageSendMessage方法后面)。

代码语言:javascript
复制
    // 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 
        }
    }
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14908762

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档