使用网络服务发现实现Java服务器和Android客户端之间的通信

5
我正在构建一个Java服务器应用程序(在PC上运行),使用JmDNS将自己注册到本地网络,并且有一个Android客户端应用程序,应该使用Network Service Discovery发现Java服务器。
当我首先运行Android应用程序,然后运行Java服务器时,该应用程序成功地发现了注册的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

服务器代码

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

}

1个回答

4
您正在注册后立即调用 jmdns.close()。只有在打开 jmdns 的情况下,您的服务才能被发现。您应该删除对 close 的调用,将您的 jmdns 变量作为类成员变量,并且当您不再希望您的服务被发现时再调用它的 close 方法。此外,在关闭 jmdns 之前调用unregisterAllServices() 是一个好习惯。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接