Wi-Fi P2P. 通知所有可用节点某个事件

5
问题:我正在制作一款离线多人android游戏,玩家可以通过Wi-fi创建或加入房间一起玩。考虑这样的情况,有一个用户创建了一个房间,他(当然)必须通知其他所有用户有一个可用的房间。那么问题来了,“怎么做呢?”我已经读了1000遍关于 的内容。上面写到为了将数据发送给另一个设备,其中一个设备应该是服务器,另一个设备则应该是客户端。客户端将信息发送给服务器,服务器接收它。所以,这是否意味着我必须让所有“玩家”都成为服务器,而“房间创建者”则需要成为客户端?这听起来很疯狂。请帮忙,也许我读错文档了?
2个回答

14
首先,你需要记住,如果你决定在你的项目中使用 WiFiP2P,那么你需要为一些困难做好准备。不幸的是(如你可能已经注意到的 :)),WiFiP2P Android 官方文档并不是那么出色。不同的设备表现出不同的行为(例如它们以不同的顺序调用一些 WifiP2P 事件),而文档根本没有涵盖此内容。要实现稳定的连接,需要采取非传统的甚至是激进的措施。获取 WifiP2P 连接与显示系统窗口密不可分(询问您是否真的想连接到设备)。
实施 WifiP2P 解决方案之前,有几件事情需要考虑:
  1. 你的游戏玩家是否能够同时连接到多个房间?
  2. 你的游戏玩家是否能够在连接到另一个房间时检测到新的房间?
  3. 你的游戏玩家是否能够为他们的房间命名为“人类可读”的名称?其他用户(而不是房间创建者)将使用这些名称来选择他们想要连接到的房间吗?

场景A:

如果你对问题1或2回答“是”,那么你需要认真考虑是否真的想使用 WifiP2PWifiP2P(Android 对 Wifi-Direct 的实现)并不完全符合你的需求。使用 WifiP2P 可能意味着房主创建一个 WifiP2P-group,而任何想要加入房间的人都必须连接到这个 WifiP2p-group。问题在于,Android 不允许单个设备同时加入多个组(这也意味着它不允许同时创建多个组)。当您已经连接到设备时,检测可用的 WiFiP2P 设备周围的更改也很困难。如果你真的想使用Wifi-Direct,你可能需要使用一个WiFiP2P-group并将所有设备连接到它。这个组会像普通网络一样运作,并且所有与游戏房间相关的东西都需要由一个节点作为典型服务器(或者可能不是典型服务器,而是其他网络解决方案)来管理。
如果你不需要WifiP2P,只需使用常规的Wifi。将所有设备连接到一个网络(甚至可以在其中一个设备上启动热点),整个连接过程可以相对简单地在后台执行,用户无需直接参与。人类可读的房间名称不是问题,因为你可以从你的服务器发送任何内容。
如果你回答第3个问题时选择了“是”,并且你确实需要使用WifiP2P,你需要找到一些方法将你的“可读”名称广播到其他设备。
你可能认为这很容易:你连接到其他设备,告诉他们你创建的房间名称,然后就完成了。但并不那么简单。正如我之前所说:
获取WifiP2P连接与显示系统窗口一起进行(询问是否确实要连接到设备)。
因此,整个过程将更多或少:
1.设备A:启动连接到设备B(此步骤也可以由设备B执行)
2.设备B:难看的系统窗口出现,询问你是否要连接到Android-ao12ij219sa(一些编程上不可更改的系统设备名称)
3.设备B:接受
4.设备B:等待连接结果
5.设备B:已连接,等待有关设备A房间名称的信息
  • 设备A:已连接,正在发送房间名称

  • 设备B:获取了设备A的房间名称,并断开连接(未来的连接请求也会导致系统窗口的显示)

  • 在执行步骤1-7期间,没有其他设备可以连接到设备A(因此在此期间没有其他设备可以获取房间名称)。

    可采取的措施:

    1. 使用WifiP2P Service Discovery。它允许广播某些信息而无需建立连接。不幸的是,它的文档甚至比WifiP2P本身还要差,可能还不太可靠(主观上)。如果您想基于此创建可靠的解决方案,您需要花费数小时进行测试并找到可能未能正常工作的不同情况。我知道从经验上说这是可能的,但需要您实现多个解决方法,以便始终获得稳定的WiFiP2P连接。

    2. 以某种其他方式向您的设备发送那些(不可更改的)WifiP2P名称与创建的房间名称之间的映射。例如通过您的服务器API或其他方式...


    非常感谢您的回复!我只有一个问题:您说服务发现可能不太可靠。这是什么意思?它会经常断开连接吗?这个问题是由硬件还是软件引起的?谢谢! - Sergey Maslov
    也许“可靠”不是最好的词。我的意思是:使用服务发现会产生大量不寻常的设备行为案例,你需要预见这些情况,以确保你的应用程序正常工作。这样你的游戏房间总是能被检测到,你的客户端总是能连接到房间,等等... - Bartek Lipinski
    @BartoszLipinski在你的回答中提到,使用WifiP2P服务发现,我可以在不需要建立连接的情况下广播一些信息,你能解释一下我该如何做吗?我的意思是,如果我在我的设备上有一个服务,我该如何广播它已经发生了变化?非常感谢。 - zer0uno
    @Bartek Lipinski,您可以使用WiFiP2pManger的setDeviceName方法,并通过反射注释@hide来使用它。我尝试使用它来更改设备名称,它完美地工作了。但是发现过程仍然存在一些奇怪的问题。例如,即使设备B的wifi关闭,设备A仍会收到包含设备B在对等列表中的WIFI_P2P_PEERS_CHANGED_ACTION意图。 - Niakros
    @BartekLipinski,非常抱歉打扰您,但您能否再帮我解决一个问题呢?我按照您在这里描述的方式实现了发现/广播系统:https://dev59.com/hV8d5IYBdhLWcg3w6luM#31641302。但是我有一个问题:当主机设备邀请对等设备时,系统对话框会出现在对等设备上,要求接受连接(对等状态变为“已邀请”,并且在WiFi重新启动之前不会更改),但它从未出现在主机上。您对此问题有什么想法吗? - Niakros
    显示剩余9条评论

    3
    基本上,我认为你的设计对于WiFi Direct的设计有非常简单的解决方案。
    要创建其他人可以加入的“房间”,只需创建一个组,然后添加本地服务以广告房间即可。
    请注意,您可能需要启动对等体发现,以便使用本地服务可见。根据我的经验,您确实需要以某种方式处于活动状态,否则您将无法被发现。
    然后,对于客户端,只需进行服务发现,并一旦找到了“房间”,直接连接即可。
    由于连接是由客户端发起的,因此接受对话框应该显示在组所有者的一侧。

    非常感谢!您能否请明确一下:服务器可以向所有连接的对等方发送数据,对吗? - Sergey Maslov
    基本上,这次的“服务器”将是Wifi Direct组的组所有者。所有客户端都将连接到组所有者,因此组所有者可以与它们通信。 - Dr.Jukka
    1
    再说了,群组信息只有群组所有者的IP地址,因此开始通信的最简单方法是从客户端开始。 - Dr.Jukka

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接