web-dev-qa-db-ja.com

ブロードキャストUDPを送信するが、他のAndroidデバイスでは受信しない

一部のブロードキャストメッセージを送信し、他のデバイスからいくつかの回答を受信するアプリを開発しようとしていますAndroid=デバイスです。他のデバイスからのUDPメッセージの受信に問題があります。これについて言及する必要がありますコードはGingerbreadで機能しましたが、JellyBeanでは機能しなくなり、問題の原因がわかりません。

ここで、ブロードキャストメッセージを送信します(他のデバイスがポート5000でリッスンしていることを知っています)。

 private void sendUDPMessage(String msg) {

    try {
        DatagramSocket clientSocket = new DatagramSocket();

        clientSocket.setBroadcast(true);
        InetAddress address = InetAddress.getByName(Utils.getBroadcastAddress());

        byte[] sendData;

        sendData = msg.getBytes();
        DatagramPacket sendPacket = new DatagramPacket(sendData,
                sendData.length, address, 5000);
        clientSocket.send(sendPacket);

        clientSocket.close();
    } catch (Exception e) {
        e.printStackTrace();
    }

}

そして、これが私が受け取る場所です:

private void start_UDP()
{
    try {
            serverSocketUDP = new DatagramSocket(5000);
        }
    catch (Exception e) {

        Log.i(LOGTAG, "Exception opening DatagramSocket UDP");
    }

    final byte[] receiveData = new byte[1024];


    while(runningUDP) {
        Log.d(LOGTAG, "Waiting for Broadcast request in ServerUDP.");

        final DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);

        serverSocketUDP.receive(receivePacket);


                byte[] sendData = new byte[1024];
                InetAddress address = receivePacket.getAddress();
                int port = receivePacket.getPort();
                if(!receivePacket.getAddress().getHostAddress().equals(Utils.getLocalIpAddress()))
                {
                    String req = new String(receivePacket.getData(), 0, receivePacket.getLength());


                    Log.d(LOGTAG, "Received UDP message : "+req+" from: "+receivePacket.getAddress().getHostAddress());
                }
                      }// while ends
       }//method ends

これら2つの関数は2つの異なるスレッドに分かれているため、同時に送受信できることを述べておきます。

次のロックも取得します。

    powerManager =(PowerManager)context.getSystemService(Context.POWER_SERVICE);
    wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK ,LOGTAG); // PARTIAL_WAKE_LOCK Only keeps CPU on
    wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
    wifiLock = wifiManager.createWifiLock(3, LOGTAG);
    multicastLock = wifiManager.createMulticastLock(LOGTAG);

    wakeLock.acquire();
    multicastLock.acquire();
    wifiLock.acquire();

そして、マニフェストファイルの権限:

<uses-permission Android:name="Android.permission.INTERNET" />
<uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission Android:name="Android.permission.ACCESS_WIFI_STATE" />
<uses-permission Android:name="Android.permission.CHANGE_WIFI_STATE" />
<uses-permission Android:name="Android.permission.WAKE_LOCK" />
<uses-permission Android:name="Android.permission.WRITE_SETTINGS"/>
<uses-permission Android:name="Android.permission.CHANGE_WIFI_MULTICAST_STATE"/>

私はメッセージがwiresharkとtcpdumpを使用して送信され、それらが送信されるかどうかをテストしました。さらに、さらに奇妙なことに、送信したブロードキャストメッセージを受信します(ただし、自分から送信されたメッセージを処理する必要がないため、メッセージを破棄します)が、他のデバイスから送信されたブロードキャストメッセージを受信しません(同じ形式で、送信元アドレスのみが異なり、メッセージが含まれます。どちらの方法でもブロードキャストメッセージには影響しません)。

私が試すことができるものはすべてなくなったので、何かアイデアがあれば教えてください。任意の助けいただければ幸いです。ありがとう!

編集:私はいくつかのテストを行いましたが、ifconfig wlan0の各電話で実行した場合でも、

  ifconfig wlan0
  wlan0: ip 169.254.17.28 mask 255.255.0.0 flags [up broadcast multicast]

これは、インターフェイスがアクティブでIPが設定されており、ブロードキャストメッセージとマルチキャストメッセージを受信できることを意味しますが、

                 InetAddress in=InetAddress.getByName("169.254.17.28");
            if (in.isReachable(1000))
                Log.i(LOGTAG, "Host is reachable");
            else
                Log.i(LOGTAG, "Host is not reachable");

ログに表示されますホストに到達できません。

ここでWi-fiをオンにします

    private void startWifiAdhoc() {

    WifiManager wifiManager =     (WifiManager)SharingFileService.context.getSystemService(Context.WIFI_SERVICE);
    String command="";
    if (condWifiAdhoc == false) {

        condWifiAdhoc=true;
        wifiInterface = Utils.getWifiInterface();


        wifiManager.setWifiEnabled(true);
        localIP = Utils.getLinkLocalAddress();
    }
    else
    {
        wifiManager.setWifiEnabled(true);
        localIP = Utils.getLinkLocalAddress();
    }
        // Set wifi ad-hoc
        command = context.getFilesDir().getPath()
                + "/iwconfig " + wifiInterface + " mode ad-hoc essid "
                + "mcp" + " channel " + "1" + " commit\n";

        Log.i(LOGTAG, command);
        Utils.rootExec(command);


        Log.i(LOGTAG, "Ip address used :" + localIP);
        command = context.getFilesDir().getPath()
                + "/ifconfig " + wifiInterface + " " + localIP
                + " netmask 255.255.0.0 up\n";



        Log.i(LOGTAG, command);
        Utils.rootExec(command);

}
19
Lara

ブロードキャストアドレスを計算するために、ここで説明する方法を使用してこれを機能させました: https://code.google.com/p/boxeeremote/wiki/AndroidUDP

これが私のレシーバーです:

try {
  //Keep a socket open to listen to all the UDP trafic that is destined for this port
  socket = new DatagramSocket(Constants.PORT, InetAddress.getByName("0.0.0.0"));
  socket.setBroadcast(true);

  while (true) {
    Log.i(TAG,"Ready to receive broadcast packets!");

    //Receive a packet
    byte[] recvBuf = new byte[15000];
    DatagramPacket packet = new DatagramPacket(recvBuf, recvBuf.length);
    socket.receive(packet);

    //Packet received
    Log.i(TAG, "Packet received from: " + packet.getAddress().getHostAddress());
    String data = new String(packet.getData()).trim();
    Log.i(TAG, "Packet received; data: " + data);

    // Send the packet data back to the UI thread
    Intent localIntent = new Intent(Constants.BROADCAST_ACTION)
            // Puts the data into the Intent
            .putExtra(Constants.EXTENDED_DATA_STATUS, data);
    // Broadcasts the Intent to receivers in this app.
    LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent);
  }
} catch (IOException ex) {
  Log.i(TAG, "Oops" + ex.getMessage());
}

そして、これが私の送信者です:

    public void sendBroadcast(String messageStr) {
    // Hack Prevent crash (sending should be done using an async task)
    StrictMode.ThreadPolicy policy = new   StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);

    try {
      //Open a random port to send the package
      DatagramSocket socket = new DatagramSocket();
      socket.setBroadcast(true);
      byte[] sendData = messageStr.getBytes();
      DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, getBroadcastAddress(), Constants.PORT);
      socket.send(sendPacket);
      System.out.println(getClass().getName() + "Broadcast packet sent to: " + getBroadcastAddress().getHostAddress());
    } catch (IOException e) {
      Log.e(TAG, "IOException: " + e.getMessage());
    }
  }

  InetAddress getBroadcastAddress() throws IOException {
    WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
    DhcpInfo dhcp = wifi.getDhcpInfo();
    // handle null somehow

    int broadcast = (dhcp.ipAddress & dhcp.netmask) | ~dhcp.netmask;
    byte[] quads = new byte[4];
    for (int k = 0; k < 4; k++)
      quads[k] = (byte) ((broadcast >> k * 8) & 0xFF);
    return InetAddress.getByAddress(quads);
  }
19
caspii

同様の問題を解決しようとしたときにあなたの投稿に出くわしました。物事はうまくいきましたか?

私の場合、Nexus 7(Jelly Bean 4.3の第1世代)とNexus One(Gingerbread 2.3.6)がUDPを介して互いに通信することを試みていました。最初は両方のデバイスで実行している私のアプリは正常にリンクアップしましたが、電話からタブレットへの一方向の通信のみでした。マニフェストに設定した許可は1つだけでした。インターネットです。マニフェストにACCESS_NETWORK_STATE権限を追加すると、タブレットから電話への通信が機能し始めました。

そのため、何らかの理由で、Nexus 7はUDPパケットの送信と受信の両方に対するINTERNET権限だけで満足しています(少なくとも、私の特定の実装では)。 Nexus OneはINTERNET権限のみで送信しますが、ACCESS_NETWORK_STATE権限も付与されていない場合は受信しません。

あなたのコードは私のものに似ています(しかし、私は "UTILS。"呼び出しを認識していません)。ただし、私の場合、テストのために、ブロードキャストアドレス(192.168.n.255)をハードコーディングしました。アドホックネットワークにいる間、私はアクセスポイントにいます。たぶん、それもいくつかの効果があります。

1
UpLate