Java多人游戏 - 网络概念

时间:2011-09-28 17:02:35

标签: java sockets networking rmi

对于学校项目,我们应该用Java创建一个多人游戏(它应该是客户端/服务器),可以在互联网上播放(我们在学校编程,所以这不是功课)。游戏是回合制的,但应该有一个聊天,其中的一个是实时的。但是,我们都没有网络编程的经验,我读的越多,我似乎就越有问题。

我的第一个想法是使用套接字API来实现多人游戏部分。服务器等待来自客户端的新数据。但是,有多种数据需要接收,如聊天消息,移动等。此外,一旦与服务器建立连接,就应该发送一些初始数据(如播放器的名称)。服务器应该能够看到它收到了什么样的消息,但是如何?我正在考虑使用字符串字段Message创建一个类type。但是在我的服务器代码中,我会得到这样的代码:

if (message.type.equals("message")) {
  // code to execute for chat messages
} else if (message.type.equals("movement")) {
  // code to execute for movement
} else if () {
  // ...
} else {
  // ...
} // Please ignore syntax errors :P

当要发送许多不同类型的数据时(并且会有),这看起来不是最有效的方式。此外,这意味着服务器和客户端都应该具有此Message-class / interface(重复代码)。

其他游戏内容呢?例如,玩家1将他的角色移动到击败另一个角色的位置。玩家1的客户计算此失败并应用正确的动作。但应该发送什么到服务器?只是新的球员位置还是失败?使用第一个选项,这意味着所有其他客户端都应该进行计算。这不会导致任何麻烦吗?由于我没有先前的网络编程经验,我对如何做所有这些事情感到有点困惑。

我还在Stackoverflow上的另一个线程中读到RMI可能是更好的选择。阅读了一些有关这方面的信息,我明白了RMI是什么,但我仍然无法看到它是否是这个项目的好选择。有什么提示吗?

如你所见,我对如何开始这个项目的网络部分感到困惑。我搜索了一些游戏编程书籍(Java forcourse),但没有一本专注于网络部分。我也搜索过Java网络书籍,但这些书籍似乎都集中在技术上,而不是优秀的代码实践上。

如果有人知道一本好书或对正确的治疗有一些建议,我们将不胜感激。

由于

2 个答案:

答案 0 :(得分:7)

你走的是正确的道路,但很少有事情可以解决。

如果你正在使用套接字,你就会发现你需要定义一个协议 - 一种用于沟通移动和游戏状态的相互语言。套接字将允许您以任何您想要的格式发送任何类型的数据。看起来你正在考虑序列化一个类Message以发送这种类型,这是一个做事。如果您使用RMI(它有自己的协议),您将表现得就像调用Java方法一样,但实际上您正在做类似的事情,序列化数据并通过套接字传递它。

在客户端和服务器之间共享代码没有任何隐含的错误 - 事实上,大多数服务以某种形式执行此操作。您的客户端和服务器都可以使用公共库来定义传递的消息类。 RMI使用方法存根来确定接口。各种Web服务定义了如何调用方法。一般的想法是只公开接口,而不是实现。

关于您的代码,为每种消息类型设置不同的Message子类可能更清晰,您可以为每条消息添加其他参数。然后,您可以拥有一个MessageProcessor类,如:

class MessageProcessor{
    void process(Move1Message m) {...}
    void process(Move2Message m) {...}
    ....

}

关于要发送的内容 - 一般原则应该是客户端负责将其移动发送到服务器,其他任何操作都是奖励,因为服务器需要验证移动的合法性。服务器应该始终是游戏状态的决定因素,以避免作弊和错误的客户端实现

除非您对学习如何实现自己的协议或使用Java套接字库感兴趣,否则使用RMI会更容易。您也可以使用SOAP,REST或任何其他协议,但我不会太费力地考虑目前使用哪一个。除了the RMI documentation之外,我没有任何建议,但我认为this book有很多关于网络的代码示例。

答案 1 :(得分:0)

当使用套接字时,每个客户端都将拥有自己的连接,服务器线程将在该连接上等待(不要忘记在客户端刷新流,否则你将永远等待)

每一行都是一个单独的消息,为区分消息类型,您可以在每条消息的开头使用“标题”(开头的特定3个字符序列)说msg,{{1 }},mov并使用trie之类的选项与开关快速决定你得到哪一个


使用RMI时,您可以让服务器保留一个管理器对象(在注册表中导出和注册),客户端可以在该对象上请求“连接”对象,该对象与套接字实现中的连接相同,但是您可以虽然回调需要以其他方式完成(使用套接字为连接做好准备),但是能够为你想做的每件事都有一个方法。