2013-06-03 85 views
2

大家好,我一直在爲此苦苦掙扎了一段時間,找不到解決方案。創建TCP套接字時無法識別Android主機名

在java中此代碼的工作:

InetAddress serverAddr = InetAddress.getByName("myservice.local"); 
Socket socket = new Socket(serverAddr, PoolServerAddress.DEFAULT_PORT); 

在Android中同樣不起作用。我試圖消除「本地」,並在清單中添加所有必要permsissions:

<uses-permission android:name="android.permission.INTERNET" /> 
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" /> 
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> 
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> 

我也試圖加入組播鎖bfore執行該代碼,但沒有辦法解決這個問題。

我得到以下異常:

06-03 13:18:14.438: W/System.err(31636): java.net.UnknownHostException: Unable to  

resolve host <server_name>: No address associated with hostname 

06-03 13:18:14.438: W/System.err(31636): at 

java.net.InetAddress.lookupHostByName(InetAddress.java:434) 

06-03 13:18:14.438: W/System.err(31636): at 

java.net.InetAddress.getAllByNameImpl(InetAddress.java:239) 

06-03 13:18:14.438: W/System.err(31636): at  

java.net.InetAddress.getByName(InetAddress.java:292) 

06-03 13:18:14.438: W/System.err(31636): at 

com.example.jelly_test.MainActivity.connect(MainActivity.java:113) 

06-03 13:18:14.438: W/System.err(31636): at  

com.example.jelly_test.MainActivity$ResolvingThread.run(MainActivity.java:71) 

06-03 13:18:14.438: W/System.err(31636): Caused by: libcore.io.GaiException:  

getaddrinfo 

failed: EAI_NODATA (No address associated with hostname) 

06-03 13:18:14.438: W/System.err(31636): at libcore.io.Posix.getaddrinfo(Native 

Method) 

06-03 13:18:14.438: W/System.err(31636): at 

libcore.io.ForwardingOs.getaddrinfo(ForwardingOs.java:55) 

06-03 13:18:14.438: W/System.err(31636): at 

java.net.InetAddress.lookupHostByName(InetAddress.java:415) 

06-03 13:18:14.438: W/System.err(31636): ... 4 mor 

如果我提供IP的服務,而不是它的工作原理,但我需要能夠提供的名稱。 此外,我已經嘗試添加JmDNS解析名稱到IP但它是緩慢的,只能在辦公室的內部服務,但我們的一些服務是外部的網絡,但他們仍然可以訪問與Java版本,但不是機器人。 還有什麼我可以嘗試嗎?非常感謝,因爲我正在用盡想法....!

編輯: 我想我的問題是由於一個事實,即有在Android上bug,它僅接受FQDN如: myservice.company.com

+0

您是否找到解決方案?如果可以,請把它張貼在這裏?我遇到了同樣的問題... –

+0

我已經寫了答案,對不起沒有找到明確的解決方法 – vallllll

回答

0

如這裏要求是我發現的選項即使在最新的Android版本(撰寫本文時爲4.4)中也暫時解決了這個問題,但該錯誤仍未得到解決。

確保您將問題中指出的所有必需權限添加到清單。

方法1:使用 庫JmDNS發現可用的服務器列表,找到你的,如果你不知道的是如何在這裏一個很好的教程: http://home.heeere.com/tech-androidjmdns.html 這種方法是緩慢的,我ahve發現,一些服務做無顯示(他們與零配置到廣告)

選項2: 要求用戶輸入完全合格的域名,如name.comany.com而不是name.local

方案3: 這是真的一個黑客,但如果你知道FQDN的類型someName.myComp.com和用戶輸入someName.local你必須刪除「本地」,並試着猜測域是什麼:

private String getTargetIp(String host) { 

    System.out.println("Will try to create socket with "+host); 

    MulticastLock multicastLock = null; 
    String ipToReturn = null; 
    Socket socket = null; 
    try { 

     WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE); 
     multicastLock = wifiManager.createMulticastLock("any_name"); 
     multicastLock.acquire(); 
     DhcpInfo info = wifiManager.getDhcpInfo(); 

     int ip = info.ipAddress; 
     InetAddress local = getInetAddress(ip); 
     String localHostName = local.getCanonicalHostName(); 
     Log.d(TAG, "Device ip addr1 = "+local +" name= "+localHostName); 
     String[] temp = localHostName.split("\\."); 

     //replace the first part with our name and obtain FQDN 
     String targetFullHostName=localHostName.replace(temp[0], host); 
     Log.d(TAG, "targetFullHostName = "+targetFullHostName); 

     //this is not mandatory but here we are trying to retrieve the ip address 
     //it maybe also a way to check if we guessed right 
     InetAddress serverAddr = InetAddress 
       .getByName(targetFullHostName); 
     socket = new Socket(serverAddr, 
       PoolServerAddress.DEFAULT_PORT); 
     ipToReturn = socket.getInetAddress().getHostAddress(); 

     Log.d(TAG, "socket remote address=" + ipToReturn); 

    } catch (UnknownHostException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    }catch(Exception e){ 
     Log.e(TAG, "Other Exception"); 
    } 

    finally { 
     if (multicastLock != null) 
      multicastLock.release(); 

     if(socket!=null) 
      try { 
       socket.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
    } 
    return ipToReturn; 

} 

方案4: 與API級別16開始,你可以使用Android服務發現聽衆列出可用服務並找到你正在尋找的那個。這與JmDNS的工作方式類似:您可以發現所有服務並嘗試在列表中找到您的服務。以下是該文檔的鏈接:http://developer.android.com/training/connect-devices-wirelessly/nsd.html#discover

相關問題