Android Wi-Fi Direct网络

7
我正在开发一款Android应用程序,我在其中寻找所有范围内的同行,并随后与它们全部连接。启动发现的设备成为组所有者,所有其他设备都成为客户端。我已完成所有连接操作,但现在我希望组所有者向所有连接的同行发送消息,如何实现?此外,请告诉我点对点通信的方法,Android中的p2p是否也使用IP来发送和接收数据?
谢谢, Talib敬礼。

你的努力取得了成功吗?如果是,请告诉我,我也遇到了同样的问题,但无法找到解决方案。我已经查阅了所有可能的文档,但都没有成功 :( :( - Bette Devine
3个回答

12

Wi-Fi Direct/P2P可以视为普通的Wi-Fi网络,但其中群组所有者(GO)充当软件访问点(dhcp服务器,配置等)。所以回答您最后一个问题,是的,Wi-Fi Direct也使用IP来发送和接收数据。

您想向组中的所有成员发送数据吗?有两种解决方案:

  1. 使用多播一次广播消息。
  2. 将消息发送到组中每个单独的客户端。

最有效的方法是第1种解决方案,使用多播广播数据,因为只需要发送一次数据。不幸的是,Android中Wi-Fi多播支持非常分散,因为许多设备似乎会阻止非单播流量。如果要选择这条路,请参见此文章获取更详细的信息。

如果您只想传输少量数据并保证在所有设备上均可支持,则解决方案2是最佳方法。GO需要知道组中客户端的IP地址,但由于Wi-Fi Direct在Android中的实现方式,仅GO IP已知于所有设备。一种解决方案是让客户端连接到GO上的套接字以获取其IP地址:

客户端代码

private static final int SERVER_PORT = 1030;

... // on group join:
wifiP2pManager.requestConnectionInfo(channel, new ConnectionInfoListener() {
    @Override
    public void onConnectionInfoAvailable(WifiP2pInfo p2pInfo) {
        if (!p2pInfo.isGroupOwner) {
            // Joined group as client - connect to GO
            Socket socket = new Socket();
            socket.connect(new InetSocketAddress(p2pInfo.groupOwnerAddress, SERVER_PORT));
        }
    }
});

群组所有者代码:

private static final int SERVER_PORT = 1030;
private ArrayList<InetAddress> clients = new ArrayList<InetAddress>();

public void startServer() {
    clients.clear();
    ServerSocket serverSocket = new ServerSocket(SERVER_PORT);

    // Collect client ip's
    while(true) {
       Socket clientSocket = serverSocket.accept();
       clients.add(clientSocket.getInetAddress());
       clientSocket.close();
    }
}

现在你需要做的就是在每个客户端上启动一个serversocket,并让GO通过迭代客户端列表创建到每个客户端的套接字连接,以发送你想要广播的消息。


想法不错,但在我的情况下无法实现。无法从群组所有者向客户端发送消息。你能帮忙吗,@nikki ashton? - Bette Devine

1

现在我们有https://github.com/libp2p/go-libp2p-pubsub - 用于处理多播消息(它也可以将网络分片成主题)

而且我们还有一些很好的对等发现协议,比如:https://github.com/libp2p/go-libp2p-examples/blob/master/chat-with-mdns/mdns.go

因此,您可以非常轻松地在本地网络中与主题消息进行多播交互,只需使用libp2p即可

我刚刚测试了https://github.com/MoonSHRD/p2chat-android,它将您需要的解决方案封装到单个库中,可以从Android使用。

到目前为止,我们可以与高级别的消息进行交互,而不是与低级别的套接字或流进行交互。希望这能帮助到某些人。

p.s. 但是,我应该注意,我还没有在Wi-Fi直连网络中测试mDNS发现


0

有几个选项可供选择,但您可以根据自己的要求进行选择。使用jmdns/jmdns广播和发现服务非常容易。以下是文档中的示例:

  • 服务注册
import java.io.IOException;
import java.net.InetAddress;

import javax.jmdns.JmDNS;
import javax.jmdns.ServiceInfo;

public class ExampleServiceRegistration {

    public static void main(String[] args) throws InterruptedException {

        try {
            // Create a JmDNS instance
            JmDNS jmdns = JmDNS.create(InetAddress.getLocalHost());

            // Register a service
            ServiceInfo serviceInfo = ServiceInfo.create("_http._tcp.local.", "example", 1234, "path=index.html");
            jmdns.registerService(serviceInfo);

            // Wait a bit
            Thread.sleep(25000);

            // Unregister all services
            jmdns.unregisterAllServices();

        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }
}
  • 服务发现
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;

import javax.jmdns.JmDNS;
import javax.jmdns.ServiceEvent;
import javax.jmdns.ServiceListener;

public class ExampleServiceDiscovery {

    private static class SampleListener implements ServiceListener {
        @Override
        public void serviceAdded(ServiceEvent event) {
            System.out.println("Service added: " + event.getInfo());
        }

        @Override
        public void serviceRemoved(ServiceEvent event) {
            System.out.println("Service removed: " + event.getInfo());
        }

        @Override
        public void serviceResolved(ServiceEvent event) {
            System.out.println("Service resolved: " + event.getInfo());
        }
    }

    public static void main(String[] args) throws InterruptedException {
        try {
            // Create a JmDNS instance
            JmDNS jmdns = JmDNS.create(InetAddress.getLocalHost());

            // Add a service listener
            jmdns.addServiceListener("_http._tcp.local.", new SampleListener());

            // Wait a bit
            Thread.sleep(30000);
        } catch (UnknownHostException e) {
            System.out.println(e.getMessage());
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }
}

如果你正在使用Java开发桌面应用程序,你的目标应该是找到最好的跨平台DNS-SD(Zeroconf、Bonjour、DNS自我发现)库。

还有其他纯Java DNS-SD实现,但不清楚它们中是否有任何一个像DNS-SD那样易于使用或经过充分测试的库。请前往Waiter一次。然而,我更喜欢通过jmdns进行,它运行良好。由于点对点连接应该使用IP(必须),一旦建立连接,您就可以轻松地发送/接收数据。


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