2015-08-24 99 views
3

我建立一個Java服務器應用程序(在PC上運行),其自身註冊使用JmDNS本地網絡和Android客戶端應用程序應該使用發現Java服務器Network Service Discovery
當我第一次運行Android應用程序,然後運行Java服務器,應用程序成功地發現了registerd Java服務器。
當我第一次運行服務器,然後android應用程序,onDiscoveryStarted方法調用,但onServiceFound方法從未觸發 - android應用程序不會發現服務器。 這在我看來是一種意想不到的行爲。使用網絡服務發現

成功案例
Android應用程序日誌:
08-24 22:42:06.157 NSD_DISCOVER的onCreate
08-24 22:42:06.373 NSD_DISCOVER:onDiscoveryStarted服務發現開始
08-24 22: 42:30.256 NSD_DISCOVER:onServiceFound已知的服務類型:_http._tcp。
08-24 22:42:30.293 NSD_DISCOVER:onServiceResolved解決成功。名稱:NsdApp,類型:._http._tcp,主持人:/10.0.0.2,端口:52288

Java服務器日誌:
START
REGISTERED
END
WAITING_FOR_MESSAGE
的hello world
END_THREAD

故障情況下

Android應用程序日誌:
08-24 22:05:21.690 NSD_DISCOVER:的onCreate
08-24 22:05:21.908 NSD_DISCOVER:onDiscoveryStarted服務發現開始

Java服務器日誌:
START
REGISTERED
END
WAITING_FOR_MESSAGE

Server代碼

public class Server { 

    public static String mServiceName = "NsdApp"; 
    public static final String SERVICE_TYPE = "_http._tcp.local"; 

    static ServerSocket mServerSocket; 


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

     System.out.println("START"); 

    try { 
     mServerSocket = new ServerSocket(0); 
    } catch (IOException e) { 
     System.out.println("ServerSocket(0) FAILED"); 
    } 

    int mPort = mServerSocket.getLocalPort(); 

    JmDNS jmdns = JmDNS.create(); 
    ServiceInfo info = ServiceInfo.create(SERVICE_TYPE, mServiceName, mPort, "B"); 
    jmdns.registerService(info); 

    System.out.println("REGISTERED"); 

    jmdns.close(); 

    Thread mReceiveMessage = new Thread(new ReceiveMessage()); 
    mReceiveMessage.start(); 

    System.out.println("END"); 
} 

public static class ReceiveMessage implements Runnable { 

    public void run() { 
     System.out.println("WAITING_FOR_MESSAGE"); 
     try { 

      Socket clientSocket = mServerSocket.accept(); 
      InputStreamReader inputStreamReader = new InputStreamReader(clientSocket.getInputStream()); 
      BufferedReader bufferedReader = new BufferedReader(inputStreamReader); 
      String message = bufferedReader.readLine(); 
      System.out.println(message); 

      bufferedReader.close(); 
      inputStreamReader.close(); 
      clientSocket.close(); 
      System.out.println("END_THREAD"); 

     } catch (IOException ex) { 
      System.out.println("Problem in message reading"); 
     } 
    } 
} 
} 

客戶端代碼

public class MainActivity extends Activity { 

public static final String TAG = "NSD_DISCOVER"; 
public static final String SERVICE_TYPE = "_http._tcp."; 
NsdManager.DiscoveryListener mDiscoveryListener; 
NsdManager.ResolveListener mResolveListener; 
NsdManager mNsdManager; 
int port; 
InetAddress host; 


@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    Log.v(TAG, "onCreate"); 

    mNsdManager = (NsdManager) getSystemService(Context.NSD_SERVICE); 
    initializeResolveListener(); 
    initializeDiscoveryListener(); 
    mNsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener); 
} 


public void initializeDiscoveryListener() { 
    mDiscoveryListener = new NsdManager.DiscoveryListener() { 

     @Override 
     public void onDiscoveryStarted(String regType) { 
      Log.v(TAG, "onDiscoveryStarted Service discovery started"); 
     } 

     @Override 
     public void onServiceFound(NsdServiceInfo service) { 
      if (!service.getServiceType().equals(SERVICE_TYPE)) { 
       Log.v(TAG, "onServiceFound Unknown Service Type: " + service.getServiceType()); 
      } else { 
       Log.v(TAG, "onServiceFound Known Service Type: " + service.getServiceType()); 
       mNsdManager.resolveService(service, mResolveListener); 
      } 
     } 

     @Override 
     public void onServiceLost(NsdServiceInfo service) { 
      Log.e(TAG, "service lost" + service); 
     } 

     @Override 
     public void onDiscoveryStopped(String serviceType) { 
      Log.i(TAG, "Discovery stopped: " + serviceType); 
     } 

     @Override 
     public void onStartDiscoveryFailed(String serviceType, int errorCode) { 
      Log.e(TAG, "Discovery failed: Error code:" + errorCode); 
      mNsdManager.stopServiceDiscovery(this); 
     } 

     @Override 
     public void onStopDiscoveryFailed(String serviceType, int errorCode) { 
      Log.e(TAG, "Discovery failed: Error code:" + errorCode); 
      mNsdManager.stopServiceDiscovery(this); 
     } 
    }; 
} 


public void initializeResolveListener() { 
    mResolveListener = new NsdManager.ResolveListener() { 

     @Override 
     public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) { 
      Log.e(TAG, "onResolveFailed Resolve failed" + errorCode); 
     } 

     @Override 
     public void onServiceResolved(NsdServiceInfo serviceInfo) { 
      Log.v(TAG, "onServiceResolved Resolve Succeeded. " + serviceInfo); 
      port = serviceInfo.getPort(); 
      host = serviceInfo.getHost(); 

      SendMessage sendMessageTask = new SendMessage(); 
      sendMessageTask.execute(); 
     } 
    }; 
} 


private class SendMessage extends AsyncTask<Void, Void, Void> { 

    @Override 
    protected Void doInBackground(Void... params) { 
     try { 

      Socket client; 
      PrintWriter printwriter; 

      client = new Socket(host, port); 
      printwriter = new PrintWriter(client.getOutputStream(), true); 
      printwriter.write("hello world"); 

      printwriter.flush(); 
      printwriter.close(); 
      client.close(); 

     } catch (UnknownHostException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 
} 

}

回答

3

正在註冊後馬上打電話jmdns.close()。只要您打開jmdns,您的服務就只能被發現。您應該刪除調用close,讓你的jmdns變量的類的成員,然後只調用close就可以了,當你不希望你的服務能夠被發現了。此外,在關閉jmdns之前調用unregisterAllServices()是一種很好的形式。