2016-12-19 98 views
4

我有極端UDP數據包丟失與Android,它沒有任何意義。這種情況如下:連接到連接到家庭網絡 java - android UDP不可靠

  • 家庭路由器的家庭網絡
  • 電話運行Java服務器(機器人)是一個全新的WRT1900ac

    1. PC上運行Java客戶端。網絡具有互聯網連接。
    2. UDP數據包很小(< 15字節)

    症狀

    1. 如果PC機發送UDP數據包到另一臺電腦(包括同一網絡上),它的工作原理很好(幾乎沒有丟包)。

    2. 如果Android向同一網絡上的PC發送UDP數據包,它也工作得很好(幾乎沒有丟包)。

    3. 如果PC在同一網絡上向Android發送UDP,則會導致極大的數據包丟失(50%或更多 - 但不盡相同)。

    大多數時候,我不得不送樣10次的數據包來獲得一個通過。其他時間都經歷了相當長的一段時間。非常奇怪的行爲,只發生在android的接收端。如果我取代 Android與PC上運行相同的代碼在Java上或只是通過Packet Sender的UDP服務器接收數據包我沒有損失問題。我注意到的另一件事是,如果不通過路由器,我會通過另一個沒有互聯網連接的接入點,或者沒有其他客戶端的性能顯着提高。這是預期的,但我的問題是,爲什麼Android的接收端看到這樣的性能差並丟失這麼多的數據包。當Android被替換爲運行相同代碼的另一臺PC並且在同一網絡上時,沒有問題。 Android沒有問題發送數據包(沒有數據包丟失)。因此它必須在接收端與其他Android相關...

    我也嘗試用分組發送器替換PC代碼,並且得到相同的結果。這個問題似乎是Android的接收端。我在PC端和android上運行相同的UDP代碼。

    的UDP發送代碼很簡單:

    public void sendMessage(String message) 
    { 
        try { 
         DatagramSocket ds = new DatagramSocket(); 
         DatagramPacket dp; 
         InetAddress local = InetAddress.getByName(ipPool); 
         dp = new DatagramPacket(message.getBytes(), message.length(), local, port); 
         ds.setBroadcast(true); 
         ds.send(dp); 
         ds.close(); 
        } catch (Exception e) { 
         e.printStackTrace(); 
        } 
    } 
    

    的UDP接收在UDP服務器類上的Android生命代碼:

    public class UDP_Server 
    { 
        CommandParser commandParser; 
    
        public UDP_Server(MainActivity mainActivity) 
        { 
         Log.i("Udp tutorial", "---------------------------Starting UDP SERVER"); 
    
         commandParser = new CommandParser(mainActivity); 
         String text; 
         int server_port = 9876; 
         try 
         { 
          DatagramSocket s = new DatagramSocket(server_port); 
          s.setBroadcast(true); 
          //s.setReceiveBufferSize(163840); 
    
    
          while (true) 
          { 
           byte[] message = new byte[1024]; 
           DatagramPacket p = new DatagramPacket(message, message.length); 
    
           s.receive(p); 
           text = new String(message, 0, p.getLength()); 
           Log.d("Udp tutorial","message:" + text); 
           //commandParser.parseCommand(text); 
           //s.close(); 
          } 
         } catch (SocketException e) 
         { 
          e.printStackTrace(); 
         } catch (IOException e) { 
          e.printStackTrace(); 
         } 
    
        } 
    } 
    

    的UDPServer。java類是通過主要活動實例「的onCreate()」方法:

    protected void onCreate(Bundle savedInstanceState) { 
         super.onCreate(savedInstanceState); 
         setContentView(R.layout.activity_main); 
    
         StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); 
         StrictMode.setThreadPolicy(policy); 
    
         wm = (WifiManager) getSystemService(WIFI_SERVICE); 
    
         Log.i("Udp tutorial", "---------------------------HERE 1"); 
         Thread thread = new Thread(new Runnable() 
         { 
          public void run() 
          { 
           UDP_Server svr = new UDP_Server(MainActivity.this); 
          } 
         }); 
    
         thread.setPriority(Thread.MAX_PRIORITY); 
         thread.start(); 
    //  TCPServer server = new TCPServer(); 
        } 
    
  • +0

    不知道這是否可以通過這種方式解決......如果您不得不使用wireshark等工具仔細觀察所有網絡流量來確定發生了什麼,它不會讓我感到意外。 – GhostCat

    +0

    如上所述,嘗試使用wireshark,看看發生了什麼。另外,如果可能的話嘗試其他Android設備,看看您的設備是否有問題。 – jython234

    回答

    0

    我曾與一些Android設備通過WiFi發送文件到TFTP(基於UDP)服務器,但它似乎工作帶來災難性的後果以及其他Android設備。

    數據塊(從設備到服務器)被正確發送,但是ack塊(從服務器到設備)似乎失去了緩衝區。

    原來我不得不獲取組播鎖定爲那些有故障的設備正常工作(學分https://www.b4x.com/android/forum/threads/enable-multicast.43321/#post-263242

    WifiManager wifi = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE); 
    WifiManager.MulticastLock multicastLock = wifi.createMulticastLock("multicastLock"); 
    multicastLock.setReferenceCounted(true); 
    multicastLock.acquire(); 
    
    ... 
    
    multicastLock.release(); 
    

    希望這有助於。