问题:我正在制作一款离线多人安卓游戏,人们可以在其中创建或加入房间并通过 Wi-fi 一起玩。考虑用户创建房间并且他(当然)必须通知所有其他用户有可用房间的情况。所以问题是“如何?”。我已经阅读了大约 1000 次this 和this。那里写着,为了将一些数据发送到另一台设备,其中一个应该是服务器,另一个应该是客户端。客户端向服务器发送一些信息,服务器接受它。那么,这是否意味着我必须让所有“玩家”成为服务器,而“房间创建者”应该成为客户端?这听起来很疯狂。请帮忙,可能我正在阅读错误的文档?
2 回答
首先,您需要记住,如果您决定WiFiP2P
在您的项目中使用,您需要为一些困难时期做好准备。不幸的是(你可能已经注意到了:))WiFiP2P
Android 的官方文档不是很好。不同的设备以不同的方式运行(例如,它们WifiP2P
以不同的顺序调用某些事件)并且文档根本没有涵盖它。实现稳定的连接需要引入非常规的,有时甚至是严厉的措施。获得WifiP2P
连接与显示系统窗口密不可分(询问您是否真的要连接到设备)。
在开始实施解决方案之前,您需要考虑几件事情WifiP2P
:
- 您的游戏玩家能否同时连接到多个房间?
- 您的游戏玩家是否能够在连接到另一个房间时检测到新房间?
- 您的游戏玩家能否使用“人类可读”的名称来命名他们的房间?其他用户(不是房间的创建者)会使用这些名称来选择他们想要连接的房间吗?
情景一:
如果您对问题 1. 或 2. 的回答为“是”,则您需要认真考虑是否真的要使用WifiP2P
. WifiP2P
(Android 的实现Wifi-Direct
)并不真正满足您的需求。使用WifiP2P
可能意味着房间所有者创建一个WifiP2P-group
,任何想要加入房间的人都必须连接到这个WifiP2p-group
。问题是 Android 不允许单个设备同时加入多个组(这也意味着它不允许同时创建多个组)。检测WiFiP2P
周围可用设备的变化也是有问题的(当您已经连接到设备时)。
如果您真的想使用Wifi-Direct
,您可能需要使用一个WiFiP2P-group
并将所有设备连接到它。该组的行为就像一个常规网络,所有与游戏室相关的东西都必须由一个充当典型服务器的节点管理(或者可能不是典型的服务器,而是其他一些网络解决方案)。
如果您真的不需要WifiP2P
使用常规的Wifi
. 将所有设备连接到一个网络(甚至可以在您的一台设备上启动热点),整个连接过程可以相对简单,在后台执行,无需用户直接参与。人类可读的房间名称不是问题,因为您可以从服务器发送任何内容。
场景 B:
如果您对问题 3 回答“是”并且您确实需要使用WifiP2P
,您将需要找到某种方法将您的“人类可读”名称广播到其他设备。
您可能认为这非常简单:您连接到其他设备,说出您创建的房间的名称,然后就完成了。没那么简单。正如我之前所说:
获得
WifiP2P
连接与显示系统窗口密不可分(询问您是否真的要连接到设备)
所以整个过程会更少:
设备A:发起连接设备B(该步骤也可以由设备B执行)
设备 B:出现丑陋的系统窗口,询问您是否要连接
Android-ao12ij219sa
(某些PROGRAMMATICALLY UNCHANGEABLE系统设备名称)设备 B:接受
设备B:等待连接结果
设备B:已连接,等待设备A的房间名称信息
设备 A:已连接,正在发送房间名称
设备B:获取设备A的房间名称,正在断开连接(以后的连接请求也会导致显示系统窗口)
在执行步骤 1-7 时,没有其他设备可以连接到设备 A(因此在此期间没有其他设备可以获取房间的名称)。
可以做什么:
使用
WifiP2P Service Discovery
. 它允许在不需要获得连接的情况下广播一些信息。不幸的是,它的记录比它本身更糟糕WifiP2P
,而且它可能更不可靠(主观上)。如果您想在此基础上制定可靠的解决方案,您将需要花费数小时的测试并找到可能无法正常工作的不同情况。我从经验中知道这是可能的,但需要您采取一些解决方法才能始终获得稳定的WiFiP2P
连接。WifiP2P
以其他方式将这些(不可更改的)名称和创建的房间名称之间的映射发送到您的设备。例如通过您的服务器 api 或其他东西...
基本上,我认为您的设计对于 Wifi Direct 的设计具有非常简单的解决方案。
基本上在创建其他人可以加入的“房间”时,只需创建一个组,然后添加本地服务来宣传该房间。
请注意,您可能需要启动对等发现,以便在本地服务中可见,至少我的经验是,您确实需要以某种方式处于活动状态,否则您将无法被发现。
然后与客户一起,只需进行服务发现,一旦找到“房间”,只需连接到它。
然后随着客户端启动连接,接受对话框应显示在组所有者侧。