那些其他的答案都比较高级,这没问题,但你不想要高级的,你想要低级的,比如“我怎样才能真正发送数据,这意味着什么,我应该发送什么等等。” 这是你需要做的:
首先,TCP还是UDP?如果你不知道这两个东西是什么,就去了解一下吧,因为我没有足够的空间在这里详细介绍它们,但对于你的选择,需要知道以下内容:
- TCP对于回合制游戏或者延迟相对较高的游戏很好,因为TCP保证数据包的传递,所以有可能需要一些时间来重新传递丢失的数据包。这对于象棋之类的回合制游戏或其他需要轮流操作的游戏非常有用。
- UDP对于那些并不关心消息可靠性,而更希望数据持续发送的游戏来说是很好的选择,如果你错过了某个消息也无所谓。这适用于实时动作类游戏,比如《光环:Reach》或《使命召唤》。在这些游戏中,如果你发送了一个物体的位置信息,但该物体从未到达目的地,那么发送一个新的位置信息要比重新发送一个旧的位置信息(现在更旧了)更好,因此并不总是需要保证可靠性。然而,你必须确保某些特定的内容百分之百可靠,比如对象的创建和销毁。这意味着你需要在UDP之上自己实现一种半可靠、基于优先级的协议。这很困难。
因此,请考虑什么是重要的,学习TCP和UDP的工作原理,然后做出明智的选择。
说到这一点,现在你需要在网络上同步对象状态。这意味着你的对象需要序列化为可以表示为字节流并写入套接字的内容。写入套接字很容易;如果你能够写入文件,那么你也能写入套接字,这真的不难。重要的是确保你能够将对象表示为缓冲区,因此如果你的对象引用/指向其他对象,你不能只发送这些指针,因为在其他客户端上它们是不同的,所以你必须将它们转换为对所有主机都通用的内容。这意味着使用ID,尽管一个对象的ID必须在所有主机上是唯一的,所以你必须有一种协调各个主机之间的方式,以确保没有两个主机会创建具有相同ID的不同对象。有办法处理主机执行此操作,但我们不会在这里担心这个问题(提示:使用主机ID和网络ID之间的某种映射。更大的提示:如果不需要,请不要这样做)。
现在你可以发送数据了,太好了,接下来呢?每当游戏状态发生变化时,你必须以某种方式向其他机器发送更新。这就是客户端-服务器架构或者点对点架构的用武之地。客户端-服务器架构更容易实现。而且,一个扮演服务器角色的主机仍然是客户端-服务器模式,任何说不同的人都是错误的。
所以,服务器的责任是“拥有”所有的游戏状态。只有服务器能够明确地说明一个对象处于什么状态。如果你想移动一个对象,你告诉服务器你想要移动,然后服务器告诉你应该移动对象,你不能自行操作(尽管某种客户端预测通常很有用)。然后服务器将更新后的对象状态发送给所有其他主机。
所以,你提到了回合制游戏,对吧?非常简单:
你要解决的是当前轮到的客户端的一个完整回合。一旦该客户端完成他们想做的事情,将该回合的结果发送给服务器。然后,服务器验证客户端的移动(不仅仅信任客户端,因为作弊就是这样发生的),并将其应用于对象状态。
一旦服务器更新完毕,它会向每个其他客户端发送消息,告知世界的新状态,然后这些客户端会应用这些更新。这包括刚刚完成回合的客户端;当服务器告诉它更新世界状态时,该客户端才应该更新自己的世界状态,因为你希望确保与其他主机的一致性,并防止主机作弊。
然后,服务器发送一条消息,指示轮到谁了。你可以在前一步中同时发送这个消息和世界状态更新,那样也可以。只是要注意客户端尝试乱序进行回合。这就是为什么服务器对世界具有权威性;如果客户端尝试作弊,服务器可以制止他们。
这就是你在回合制游戏中需要做的全部。提示:使用TCP。
更大的提示:TCP实现了一种称为“Nagle算法”的东西,它将你的消息合并成一个单独的数据包。这意味着,如果你通过两次分别调用“Send”发送了两个独立的消息,可能对方主机在一次调用“Receive”时只会接收到一个数据包,但该数据包将包含被发送的两个数据包的内容。因此,如果你通过两次发送调用发送了两个100字节的数据包,可能在一次接收调用时会得到一个200字节的数据包。这是正常的,所以你需要想办法处理这个问题。一个技巧是让每个数据包的大小都相同,然后每次检查输入时从套接字中读取相同数量的字节。同时要记住,你也可能会收到部分消息。例如,如果你发送了两个100字节的消息,它们可以合并成一个200字节的消息。接下来,如果你在另一端的套接字上读取,但你使用了150字节的缓冲区大小进行读取,你将得到150字节的数据,其中包含第一个数据包和第二个数据包的一部分。你将不得不再次调用接收来获取第二个消息的剩余部分,所以要记录下你已经接收到多少数据,以免在某个地方丢失部分数据包。这就是为什么保持数据包大小相同很有用的原因。
还有一些其他有用的技巧可以减小消息的大小和频率,并跟踪实时非回合制游戏,但如果你的游戏是回合制的,那么正确的做法可能是使用TCP,不必担心其他问题。以下是一些有用的网站和文章链接,可以提供更多关于游戏网络编程的信息:
如果你想了解更多细节或有更具体的问题,请告诉我。