2013-06-25 14 views
11

Próbuję opracować aplikację, która wysyła niektóre wiadomości rozgłoszeniowe i otrzymuje odpowiedzi z innych urządzeń z Androidem. Mam problem z odbieraniem wiadomości UDP z innych urządzeń. Powinienem wspomnieć, że ten kod działał na Gingerbread, ale na JellyBean to już nie działa i nie wiem, jaki może być problem.Wysyłaj transmisję UDP, ale nie odbieraj jej na innych urządzeniach z Androidem.

Tutaj jest gdzie wysłać komunikat rozgłoszeniowy (znam inne urządzenia nasłuchuje na porcie 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(); 
    } 

} 

A oto gdzie otrzymam go:

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 

należy wspomnieć, że te 2 funkcje są oddzielne w 2 różnych wątkach, więc mogę wysyłać i odbierać jednocześnie.

ja również nabyć następujące zamki:

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(); 

A uprawnienia do pliku manifestu:

<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"/> 

I sprawdzili, czy wiadomości są wysyłane przy użyciu Wireshark i tcpdump i ich wysłania. Co więcej, co jeszcze dziwniejsze, odbieram wysyłane wiadomości, które wysyłam (ale odrzucam je, ponieważ nie muszę przetwarzać wiadomości wysłanych ode mnie), ale nie odbieram wiadomości rozgłoszeniowych wysyłanych z innych urządzeń (które powinny mieć ten sam format, tylko adres źródłowy byłby inny, a wiadomość zawarta w żaden sposób nie powinna wpływać na komunikat rozgłoszeniowy).

Proszę dać mi znać, jeśli masz jakieś pomysły, bo zabrakło mi wszystkiego, co mógłbym spróbować. Każda pomoc będzie doceniona. Dzięki!

EDIT: Zrobiłem kilka testów, a nawet jeśli, gdy biegnę na każdym z wlan0 telefony ifconfig i mówi coś

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

co oznacza, że ​​interfejs jest aktywny, a IP jest ustawiony, może odbierać wiadomości rozgłoszeniowe i wiadomości multiemisyjne, ale gdy używam

    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"); 

To pokazuje, że w logi host nie jest osiągalny.

To gdzie mam włączyć 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); 

} 
+0

pamiętać, że niektóre routery wyłączają domyślnie DNS rozsyłania grupowego. – yorkw

+0

oh ... Muszę wspomnieć, że jestem w WiFi adhoc – Lara

+0

Możesz chcieć spojrzeć na ten post: http://stackoverflow.com/a/16208617/1028256 Mówi, że niektórzy kierowcy wifi mogą wyłączyć odbiorniki, ale w takim przypadku dzieje się to po wznowieniu z trybu uśpienia. – Mixaz

Odpowiedz

1

natknąłem postu, kiedy stara się rozwiązać podobny problem. Czy twoje rzeczy działały?

W moim przypadku próbowałem zdobyć Nexus 7 (pierwszy gen z Jelly Bean 4.3) i Nexus One (Gingerbread 2.3.6) rozmawiający ze sobą przez UDP. Początkowo moja aplikacja, działająca na obu urządzeniach, z powodzeniem łączyła się, ale tylko z jednokierunkową komunikacją z telefonu do tabletu. W manifeście miałem tylko jedno zezwolenie: INTERNET. Komunikacja z tabletu do telefonu rozpoczęła się po dodaniu uprawnienia ACCESS_NETWORK_STATE do manifestu.

Tak więc, z jakiegoś powodu, Nexus 7 jest zadowolony z uprawnień INTERNETowych zarówno do wysyłania, jak i odbierania pakietów UDP (przynajmniej moja konkretna implementacja).Nexus One będzie wysyłać tylko z uprawnieniami INTERNET, ale nie otrzyma, chyba że przyznane zostanie również uprawnienie ACCESS_NETWORK_STATE.

Twój kod wygląda podobnie do mojego (nie rozpoznaję jednak Twoich połączeń "UTILS"). W moim przypadku jednak do celów testowania zakodowałem adres emisji (192.168.n.255). Jestem w punkcie dostępowym, gdy jesteś w sieci adhoc. Być może to również ma pewien wpływ.

12

mam to działa przy użyciu metody opisanej tutaj, aby obliczyć adres rozgłoszeniowy: https://code.google.com/p/boxeeremote/wiki/AndroidUDP

Oto mój odbiornik:

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()); 
} 

A oto mój nadawca:

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); 
    } 
+0

Czy ten kod działa tylko wtedy, gdy urządzenia są w tej samej sieci lokalnej? – zer0uno

+0

Tak, to jest poprawne – caspii

+0

zweryfikowane na Android 5.1.1 i Android 7.1.2 –

Powiązane problemy