您会为回合制游戏服务器使用什么 RESTful API?
如何将回合制游戏服务器建模为 RESTful API? 例如,一个国际象棋服务器,您可以在其中与同一 API 的另一个客户端下棋。 您需要某种方式来请求并与其他客户端协商游戏,以及某种方式来玩游戏的各个动作。
这是 REST (RESTful) API 的良好候选者吗? 或者应该以不同的方式建模?
How would you model a turn-based game server as a RESTful API? For example, a chess server, where you could play a game of chess against another client of the same API. You would need some way of requesting and negotiating a game with the other client, and some way of playing the individual moves of the game.
Is this a good candidate for a REST (RESTful) API? Or should this be modelled a different way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
我的想法是这样的:
就基本资源而言。 我不知道如何处理“其他玩家移动了吗?” 不过,这个想法。 我考虑过简单地在移动开始之前阻止 GET 请求 - 即我的客户端会将我移动的坐标放置到
,然后 GET
服务器不会立即响应,而是保持连接打开,直到其他玩家移动(即放置到该位置)。 这就是中岛所说的“彗星式”吗?
查理,我不太清楚你所说的轮到谁的“令牌”是什么意思——这是否可以解决同样的问题而不需要轮询或阻塞连接?
对于玩家 ID,将其建模为 URL 中的资源是否有意义? 我打算简单地使用 HTTP 用户身份验证(其中用户/通行证作为每个请求的一部分发送)。 您仍然可以在没有身份验证的情况下获取大多数资源,但如果您尝试这样做,
如果您没有该游戏的正确凭据,则会出现权限被拒绝错误。
I'm thinking something like:
as far as the basic resources are concerned. I'm not sure how to handle the "has the other player moved yet?" idea, though. I've thought about simply having the GET request block until the move is played--i.e. my client would PUT the coordinates of my move to
and then would GET
The server would not respond immediately, but keep the connection open until the other player moved (i.e. PUT to that location). Is this what nakajima is referring to as "comet-esque"?
Charlie, I'm not quite sure what you meant by the "token" for whose turn it is--does this solve the same problem without the need for polling or a blocking connection?
For player IDs, does it make sense to model those as a resource in part of the URL? I was planning to simply use HTTP user authentication (where the user/pass is sent as part of every request). You could still GET most resources without authentication, but if you tried to, say,
it would give you a permission denied error if you didn't have the correct credentials for that game.
好吧,REST 的基本思想是转移状态; 您希望服务器上有很少或没有“会话状态”。 所以你不会想使用会话状态和保持活动,这正是 Comet 所做的。 但想一想邮寄游戏的例子:你们都有棋盘的副本,并且交换棋步。 邮局不知道这个游戏。
现在,我承认,当我思考这个问题时,这个想法正在我的脑海中增长——事实上,我可能会根据这个问题写一篇文章——但这个想法是这样的,就像一些故事一样:
行,因此您可以转到已知的 URI
得到一个。 你返回一个页面
显示谁(如果有人)正在等待
开始游戏。
播放,然后单击相应的
关联。 你会得到一个新的显示(ajax
如果你愿意的话,这里有魔法)
董事会成立。 你们中的一个是白人,
白棋先走。
采取行动并承诺(例如采取
在游戏中你的手离开了棋子。)
董事会更新和权利
移动到另一位玩家。
在服务器状态方面你不需要太多东西——尽管你可能想通过跟踪移动等来扩展它,比如说排名——而谁有权移动的问题可以完全从棋盘页面:如果您有权利,您将有一个用于输入棋步的表格; 当您发回表单返回时,响应会向您返回一个页面,其中没有用于输入移动的位置。
我所说的“令牌”只是指状态“我的举动”/“你的举动”的某种任意表示。
似乎您需要的资源是
每个活跃游戏都有
OKay, the basic idea of REST is that you're transferring the state; you want to have little or no "session state" on the server. So you wouldn't want to use session state and a keepalive, which is what Comet does. But think about the example of a play-by-mail game: You both have a copy of the board, and you exchange moves. The Post Office doesn't know about the game.
Now, I'll admit this is growing in my mind as I think about it -- in fact, I may write an article based on this question -- but here's the idea, as some stories:
line, so you go to a known URI to
get one. You get back a page
showing who, if anyone, is waiting
to start a game.
to play, and click the appropriate
link. You get a new display (ajax
magic in here if you want) with the
board set up. One of you is white,
white moves first.
a move, and commits (like taking
your hand off the piece in a game.)
The board updates and the right to
move goes to the other player.
You don't need anything much in terms of server state --- although you might want to extend this by keeping track of moves etc, say for ranking -- and the question of who has the right to move can be computed entirely from the board page: if you have the right, you have a form for entering a move; when you send the form return back, the response returns a page to you with no slot for entering a move.
By "the token" I just mean some arbitrary representation of that one bit of state "My move"/"your move".
Seems as if the resources you need are
and such
您尝试建模的资源是什么? 我似乎有四个:你,你的对手,特定的游戏(会话,实例)和游戏板状态。 因此,首先
我们要对 InfoQ 进行很好的介绍/概述。
What are the resources you're trying to model? I would seem to have four: You, your opponent, the particular game (session, instance) and the game board state. So it would start with something like
we've got a good intro/overview on InfoQ.
我认为 REST 对于此类应用程序来说不是一个好的选择。 您需要执行的转换和操作(进行移动、查看移动历史记录、撤消、获取建议、转向通知)并未完全映射到 REST 的资源概念。 (如果考虑一下用于更复杂的回合制游戏(例如 Scrabble 或 Monopoly)的 RESTful API 的外观,困难可能会更加明显。)
我认为任何明智的 REST API 可能最终都会成为非 RESTful 事物的包装器,例如作为一种有状态协议,来回发送便携式游戏符号。
I don't think REST is a good choice for such an application. The transformations and operations you need to do (make move, view move history, undo, get suggestion, turn notification) do not map neatly to REST's concept of resources. (The difficulties are perhaps more obvious if one considers how a RESTful API for more complicated turn-based games such as Scrabble or Monopoly might look.)
I think any sensible REST API would probably end up being a wrapper around something non-RESTful, such as a stateful protocol that sent portable game notation back and forth.
谢谢,查理。 我仍然不清楚你是如何在你的计划中得到对手行动的通知的。 当然,谁有权移动的问题可以简单地计算出来——要么根据董事会资源,要么使用明确说明轮到谁移动的单独资源。 但客户端如何知道该资源已更改? 它是否必须简单地不断轮询,记住以前的状态,直到注意到某些事情发生了变化? 在邮局模型中,邮局将消息“推送”到客户端(您的邮箱),这在 HTTP 中是不可能的。
我想这是一个更普遍的问题的一部分:如果我想监视某个 REST 资源的更改或修改,那么最好的方法是什么? 服务器可以做些什么来让客户端更容易做到这一点吗?
我想我实际上会把这个问题作为一个单独的问题发布,因为我认为它本身很有趣。
编辑添加: 什么是 RESTful监视 REST 资源变化的方法?
Thanks, Charlie. I'm still not clear how you get notified of the opponent's move in your scheme. Of course the question of who has the right to move can be computed simply--either from the board resource, or by using a separate resource that explicitly states whose turn it is to move. But how does a client know that this resource has changed? Does it have to simply continually poll, remembering the previous state, until it notices something has changed? In the Post Office model, the Post Office "pushes" a message to the client (your mailbox), which is not possible in HTTP.
I suppose this is part of a more general question: if there is a REST resource that I want to monitor for changes or modifications, what is the best way to do so? And is there something the server can do to make this easier for the client?
I think I'll actually post this as a separate question since I think it's interesting by itself.
Edited to add: What is a RESTful way of monitoring a REST resource for changes?
planet.jabber 的一名开发人员参与了 Chesspark,一个在线国际象棋社区。 他们广泛使用 Jabber/XMPP; 如果我没记错的话,这些是他关于该主题的帖子。
XMPP 是一种即时消息协议,大致基于小型 XML 消息交换。 大多数语言都有库,包括 Javascript。 不过,我不确定它是否能解决您的问题。
One of the developers in planet.jabber is involved in Chesspark, an online chess community. They are using Jabber/XMPP extensively; if I'm not mistaken, these are his posts on the subject.
XMPP is an instant-messaging protocol, roughly based on small XML message exchange. There are libraries for most languages, including Javascript. I'm not sure it will fit your problem, though.
我认为您可以 RESTful 方式建模。 实现将会更加困难,因为您要么需要 comet)式的解决方案,否则您必须通过 AJAX 以相对较短的间隔轮询服务器。
就如何公开 RESTful 界面而言,我想说您需要一个带有坐标的游戏板、可以占据这些坐标的棋子以及改变这些坐标的操作。
当玩家采取行动时,就会创建一个新的动作。 验证并确保允许后,您将更新游戏的状态,然后呈现更新 UI 所需的任何响应。
这基本上就是我建模的方式。 不过,我认为实施方面是更大的困难。
I think you could model it RESTfully. Implementing it will be more difficult, because you'd either need a comet)-esque solution or you'd have to be polling the server at a relatively short interval via AJAX.
In terms of how you'd expose a RESTful interface, I'd say that you need a playing board with coordinates, pieces that can occupy those coordinates, and actions that alter those coordinates.
When a player makes a move, a new action would be created. After validating to make sure it's allowed, you'd update the status of the game, then render whatever response is needed to update the UI.
So that's basically how I'd model it. The implementation side is what I'd consider the bigger difficulty here though.
我不认为事情有那么复杂,中岛。 您可以传递棋盘位置、动作的数据(例如 JSON 格式),以及谁有下一步动作的令牌。 这就像通过邮件玩游戏一样。
你首先要进入游戏并寻找合作伙伴,所以
会给你一份等待的人名单。 当你进来时,如果没有人在等你就得到一个游戏ID; 否则你就选择一个正在等待的人并获取他们拥有的游戏ID。
向您展示董事会。 你需要一些东西来决定谁玩白棋,我将把它留作练习。 GET 操作给你棋盘,所以 POST 发送一个棋步; 如果您没有移动,则会出现错误。 您可以通过下一个 GET 找到结果。
天哪,在这个模型中我什至没有使用玩家 ID,尽管它可能很好,这样就没有人可以作为一个 kibitzer 潜入游戏。
I don't think it's all that complciated, Nakajima. You'd pass data, say in JSON, for the board position, for the moves, and with a token for who has the next move. It'd be exactly like playing by mail.
You start by going to the game and looking for a partner, so
gives you a list of people waiting. when you come in, if there is no one waiting you get a game ID; otherwise you pick someone waiting and get the game ID they have.
shows you the board. You need something to set up the decision of who plays white, i'll leave that as an exercise. The GET operation gives you the board, so a POST sends a move; if you don't have the move you get an error. You find the result by the next GET.
Hell, in this model I'm not even using the gamer ID, although it might be good so no one can sneak into the game as a kibitzer.
所以你的想法是,不是让动作成为一流对象,而是将每个动作视为游戏本身的更新? 这当然是一种不同的方法,尽管我认为出于几个原因我更愿意将操作对象拆分为它自己的第一类实体。 最大的原因是我相信它更容易测试。 移动是否有效可以存在于动作对象中,而不需要担心棋盘始终处于有效状态。 当然,我不知道这两种方法会带来什么,但这对我来说感觉更好。
另一个原因(您可以通过 YAGNI 完全反驳)是,第一类动作对象将提供动作历史记录。 也许有趣,但除非有要求,否则是一个没有实际意义的问题。
So your thought is that instead of making the actions a first class object, each move would be treated as an update of the game itself? It's certainly a different way to do it, though I think I'd prefer to split the action object out into its own first class entity for a couple reasons. The biggest reason is that I believe it's more testable. Whether or not a move is valid could live in the action object, instead of needing to worry about the board being in a valid state at all times. Granted, I don't know what either approach would entail, but this feels better to me.
The other reason, which you can totally refute via YAGNI, is that a first class action object would provide a history of moves. Interesting perhaps, but unless a requirement, is a moot point.
对于像国际象棋这样的简单游戏,实际上只需定义媒体类型即可。
下面是一个用于模拟国际象棋游戏的可能过于简化的媒体类型的示例。
我将跳过对可能在同一服务器上运行的多个游戏的管理,而只对已经运行的游戏进行建模。
第一步通常是定义应用程序的索引。
index
游戏的入口点。 获取此信息以发现有关游戏的信息。
有效负载可能如下所示:
move
将 JSON 有效负载发布到标有
move
的rel
的链接以移动一块。 必须包含以下字段:成功响应的状态代码为 200,并将包含与
index
有效负载相同的实体,并具有更新的状态游戏。如果不允许用户将他的棋子移动到那里,或者如果没有轮到他,则返回 400。
player
获取玩家的描述。
响应中必须包含以下字段:
piece
片段嵌入在
index
有效负载中,但可以独立存在。 每个片段
必须具有以下字段:每件作品都必须有一个
移动
链接。我可以在这里做出的另一种设计决策是为每个有效的动作提供单独的链接。 这样做可能有充分的理由,但我想证明这不是必需的。 您可能还需要包含一些其他资源来处理诸如帮助客户确定轮到谁以及诸如此类的事情。
对于更复杂的游戏,例如《文明》、RTS、FPS 或 MMOG 等,在我看来这可能不太实用。
For a simple game like chess, it is really just about defining the mediatype.
Here is an example of what is probably an over simplified mediatype to model a chess game.
I'm going to skip the management of multiple games that may be running on the same server and just model an already running game.
The first step is usually to define an index to the application.
index
The entry point for the game. Fetch this to discover information about the game.
The payload might look something like this:
move
POST a JSON payload to links marked with a
rel
ofmove
to move a piece. The following fields MUST be included:Successful responses have a status code of 200 and will contain an entity that the same as the
index
payload with the updated state of the game.400 if the user is not allowed to move his piece there, or if it isn't his turn.
player
GET a description of a player.
The following fields MUST be in the response:
piece
Pieces are embedded in the
index
payload, but MAY exist on their own. Eachpiece
MUST have the following fields:Each piece MUST have a
move
link.An alternative design decision I could have made here was to provide an individual link for every valid move. There may be good reasons to do that, but I wanted to demonstrate that it isn't required. There are probably a handful of other resources that you would want to include to handle things like helping the client determine whose turn it is and whatnot.
For more complicated games, like Civilization, RTSs, FPSs, or MMOGs and what not, this may not be so practical IMO.