简体   繁体   English

使用网络服务发现在Java服务器和Android客户端之间进行通信

[英]communication between Java server and Android client using Network Service Discovery

I'm building a Java server application (running on a pc) that register itself to the local network using JmDNS , and an Android client App that should discover the java server using Network Service Discovery . 我正在构建一个Java服务器应用程序(在PC上运行),它使用JmDNS将自己注册到本地网络,以及一个应该使用网络服务发现来发现java服务器的Android客户端应用程序。
When I run the android app first, and then run the java server, the app succeed to discover the registerd java server. 当我首先运行Android应用程序,然后运行java服务器时,应用程序成功发现注册的java服务器。
But when I first run the server and then the android app, the onDiscoveryStarted method called but the onServiceFound method never triggered - the android app doesn't discover the server. 但是当我第一次运行服务器然后运行Android应用程序时, onDiscoveryStarted方法被调用但是onServiceFound方法从未被触发 - android应用程序没有发现服务器。 This seems to me as an unexpected behavior. 这在我看来是一种意想不到的行为。

Succeed case : 成功案例
Android app log: Android应用日志:
08-24 22:42:06.157 NSD_DISCOVER onCreate 08-24 22:42:06.157 NSD_DISCOVER onCreate
08-24 22:42:06.373 NSD_DISCOVER﹕ onDiscoveryStarted Service discovery started 08-24 22:42:06.373 NSD_DISCOVER:onDiscoveryStarted服务发现已启动
08-24 22:42:30.256 NSD_DISCOVER﹕ onServiceFound Known Service Type: _http._tcp. 08-24 22:42:30.256 NSD_DISCOVER:onServiceFound已知服务类型:_http._tcp。
08-24 22:42:30.293 NSD_DISCOVER﹕ onServiceResolved Resolve Succeeded. 08-24 22:42:30.293 NSD_DISCOVER:onServiceResolved Resolve Succeeded。 name: NsdApp, type: ._http._tcp, host: /10.0.0.2, port: 52288 name:NsdApp,type:._ http._tcp,host:/10.0.0.2,port:52288

Java server log: Java服务器日志:
START 开始
REGISTERED 注册
END 结束
WAITING_FOR_MESSAGE WAITING_FOR_MESSAGE
hello world 你好,世界
END_THREAD END_THREAD

Failure case : 失败案例

Android app log: Android应用日志:
08-24 22:05:21.690 NSD_DISCOVER﹕ onCreate 08-24 22:05:21.690 NSD_DISCOVER:onCreate
08-24 22:05:21.908 NSD_DISCOVER﹕ onDiscoveryStarted Service discovery started 08-24 22:05:21.908 NSD_DISCOVER:onDiscoveryStarted服务发现开始了

Java server log: Java服务器日志:
START 开始
REGISTERED 注册
END 结束
WAITING_FOR_MESSAGE WAITING_FOR_MESSAGE

Server code 服务器代码

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

Client code 客户代码

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

} }

You are calling jmdns.close() right after registering. 您在注册后立即调用jmdns.close() Your service is only discoverable as long as you have jmdns open. 只要您打开jmdns,您的服务才能被发现。 You should remove that call to close , make your jmdns variable a member of your class, and then only call close on it when you don't want your services to be discoverable anymore. 您应该删除该调用以close ,使您的jmdns变量成为您的类的成员,然后只在您不希望您的服务被发现时才调用close。 Also, it is good form to call unregisterAllServices() before closing jmdns. 此外,在关闭jmdns之前调用unregisterAllServices()是一种很好的形式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Java套接字(服务器)和C ++套接字(客户端)之间的网络通信 - Network Communication between a java socket (server) and a C++ socket (client) Java服务器android客户端通过不同网络进行通信 - Java server android client communication over different network Java服务器与客户端之间的通信 - Communication between Java server and Client 使用通信层在客户端和服务器之间进行通信 - Using a communication layer for communication between a Client and a Server 使用套接字在服务器(ANSI C)和客户端(JAVA)之间进行通信 - Communication between server (ANSI C) and client (JAVA) using sockets 如何使用WebSocket在UWP Client和Java Server之间进行通信? - How to make communication between UWP Client and Java Server using WebSocket? 服务器应用程序和使用Java的Matlab客户端之间的套接字通信 - Socket communication between server app and Matlab client using Java C# 服务器和 JAVA 客户端之间的网络通信:如何处理。 过渡? - Network communication between C# server and JAVA client: how to handle that. transition? Java服务器与Matlab客户端之间的通信 - Communication between java server and matlab client 客户端上的Java服务器与Javascript之间的套接字通信 - Socket Communication between Java server on client and Javascript
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM