问:
Android, NSD/DNS-SD: NsdManager unreliable discovery and IP resolution
In the course of the last weeks, Android's NSD implementation is making me go mad:

From a user's point of view, the following problems arise:

Devices discover each other in a completely non-deterministic fashion. If I launch my NsdManager-based app, it works more or less if only two devices are involved. If a third device joins, it will seldomly discover the first two, and the first two will not see the third. If I exit the apps (they gracefully unregister the NSD listeners) and restart them in a different order, the discovery pattern is not exactly the same, but similar.

In my home network, the IP resolution of the discovered devices basically works as expected. At work, sometimes even when only using two devices (A and B), device A will resolve device B's service with A's IP address and B's port and vice-versa. So somehow the IP address and service name seem to get mixed up at a lower level (probably the NsdManager).

I've now filed a bug report on Google code for this (https://code.google.com/p/android/issues/detail?id=201314&thanks=201314&ts=1455814995). I'm posting this here too in hope to get more feedback; maybe I got something in my Nsd helper class wrong.

First of all, after endless debugging, I have now found hints in the logcat that Android's underlying NsdService itself might be malfunctioning, while MDnsDS seems to work correctly. But I'm unsure...

Here's some log output that illustrates the problem (some messages filtered for readability):

```<code>02-18 16:57:02.327: D/NsdService(628): startMDnsDaemon
02-18 16:57:02.327: D/MDnsDS(187): Starting MDNSD
02-18 16:57:02.529: D/NsdService(628): New client listening to asynchronous messages
02-18 16:57:02.529: D/NsdService(628): New client, channel: com.android.internal.util.AsyncChannel@1fa188ce messenger: android.os.Messenger@cca33ef
02-18 16:57:02.532: D/NsdService(628): Register service
02-18 16:57:02.532: D/NsdService(628): registerService: 106 name: TuSync-0.57392, type: _tusync._tcp., host: /::, port: 57392
02-18 16:57:02.533: D/MDnsDS(187): serviceRegister(106, (null), TuSync-0.57392, _tusync._tcp., (null), (null), 57392, 0, <binary>)
02-18 16:57:02.533: D/MDnsDS(187): serviceRegister successful
02-18 16:57:02.534: D/NsdService(628): Register 1 106
02-18 16:57:04.083: D/MDnsDS(187): register succeeded for 106 as TuSync-0.57392
02-18 16:57:04.087: D/NsdService(628): SERVICE_REGISTERED Raw: 606 106 "TuSync-0.57392"
02-18 16:57:04.109: D/NsdService(628): Discover services
02-18 16:57:04.109: D/NsdService(628): discoverServices: 107 _tusync._tcp.
02-18 16:57:04.110: D/MDnsDS(187): discover((null), _tusync._tcp., (null), 107, 0)
02-18 16:57:04.110: D/MDnsDS(187): discover successful
02-18 16:57:04.110: D/NsdService(628): Discover 2 107_tusync._tcp.
02-18 16:57:04.333: D/MDnsDS(187): Discover found new serviceName TuSync-0.57392, regType _tusync._tcp. and domain local. for 107
02-18 16:57:04.334: D/NsdService(628): SERVICE_FOUND Raw: 603 107 "TuSync-0.57392" _tusync._tcp. local.
02-18 16:57:04.338: D/NsdService(628): Resolve service
02-18 16:57:04.338: D/NsdService(628): resolveService: 108 name: TuSync-0.57392, type: _tusync._tcp., host: null, port: 0
02-18 16:57:04.339: D/MDnsDS(187): resolveService(108, (null), TuSync-0.57392, _tusync._tcp., local.)
02-18 16:57:04.345: D/MDnsDS(187): startMonitoring 108
02-18 16:57:04.345: D/MDnsDS(187): resolveService successful
02-18 16:57:04.346: D/MDnsDS(187): resolve succeeded for 108 finding TuSync-0\.57392._tusync._tcp.local. at Android-3.local.:57392 with txtLen 1
02-18 16:57:04.347: D/NsdService(628): SERVICE_RESOLVED Raw: 608 108 "TuSync-0\\.57392._tusync._tcp.local." "Android-3.local." 57392 1
02-18 16:57:04.347: D/NsdService(628): stopResolveService: 108
02-18 16:57:04.347: D/MDnsDS(187): Stopping resolve with ref 0xb5c4734c
02-18 16:57:04.349: D/NsdService(628): getAdddrInfo: 109
02-18 16:57:04.349: D/MDnsDS(187): getAddrInfo(109, (null) 0, Android-3.local.)
02-18 16:57:04.350: D/MDnsDS(187): getAddrInfo successful
02-18 16:57:04.352: D/MDnsDS(187): getAddrInfo succeeded for 109: 109 "Android-3.local." 120 10.0.0.4
02-18 16:57:04.352: D/MDnsDS(187): getAddrInfo succeeded for 109: 109 "Android-3.local." 120 fe80::204:4bff:fe2c:6c87
02-18 16:57:04.354: D/NsdService(628): SERVICE_GET_ADDR_SUCCESS Raw: 612 109 "Android-3.local." 120 10.0.0.4
02-18 16:57:04.354: D/NsdService(628): stopGetAdddrInfo: 109
02-18 16:57:04.355: D/MDnsDS(187): Stopping getaddrinfo with ref 0xb5c472d4
02-18 16:57:04.364: E/NsdService(628): Unique id with no client mapping: 109
02-18 16:57:04.364: E/NsdService(628): Unhandled { when=-10ms what=393242 obj=com.android.server.NsdService$NativeEvent@86af300 target=com.android.internal.util.StateMachine$SmHandler }
02-18 16:57:04.627: D/MDnsDS(187): Discover found new serviceName TuSync-0.36230, regType _tusync._tcp. and domain local. for 107
02-18 16:57:04.632: D/MDnsDS(187): Discover found new serviceName TuSync-0.60493, regType _tusync._tcp. and domain local. for 107
02-18 16:57:04.633: D/NsdService(628): SERVICE_FOUND Raw: 603 107 "TuSync-0.36230" _tusync._tcp. local.
02-18 16:57:04.634: D/NsdService(628): SERVICE_FOUND Raw: 603 107 "TuSync-0.60493" _tusync._tcp. local.
02-18 16:57:04.635: D/NsdService(628): Resolve service
02-18 16:57:04.635: D/NsdService(628): resolveService: 110 name: TuSync-0.36230, type: _tusync._tcp., host: null, port: 0
02-18 16:57:04.636: D/MDnsDS(187): resolveService(110, (null), TuSync-0.36230, _tusync._tcp., local.)
02-18 16:57:04.637: D/MDnsDS(187): resolve succeeded for 110 finding TuSync-0\.36230._tusync._tcp.local. at Android.local.:36230 with txtLen 1
02-18 16:57:04.638: D/NsdService(628): Resolve service
02-18 16:57:04.638: D/NsdService(628): SERVICE_RESOLVED Raw: 608 110 "TuSync-0\\.36230._tusync._tcp.local." "Android.local." 36230 1
02-18 16:57:04.639: D/NsdService(628): stopResolveService: 110
02-18 16:57:04.639: D/MDnsDS(187): Stopping resolve with ref 0xb5c473c4
02-18 16:57:04.643: D/MDnsDS(187): getAddrInfo succeeded for 111: 111 "Android.local." 120 10.0.0.5
02-18 16:57:04.643: D/MDnsDS(187): getAddrInfo succeeded for 111: 111 "Android.local." 120 fe80::204:4bff:fe26:8483
02-18 16:57:04.644: D/NsdService(628): SERVICE_GET_ADDR_SUCCESS Raw: 612 111 "Android.local." 120 10.0.0.5
02-18 16:57:04.644: D/NsdService(628): stopGetAdddrInfo: 111
02-18 16:57:04.645: D/MDnsDS(187): Stopping getaddrinfo with ref 0xb5c47364
02-18 16:57:04.645: D/MDnsDS(187): Going to poll with pollCount 3
02-18 16:57:04.658: E/NsdService(628): Unique id with no client mapping: 111
02-18 16:57:04.658: E/NsdService(628): Unhandled { when=-14ms what=393242 obj=com.android.server.NsdService$NativeEvent@1d93a739 target=com.android.internal.util.StateMachine$SmHandler }
</code>```

Some notes on the context:

My NSD service type is _tusync._tcp.

I create unique service names for all nodes in the format TuSync-0.[local port number] to prevent naming conflicts and ease debugging.

In this test scenario, there are three devices. The logging device's IP is 10.0.0.4, port 57392.

The log shows, that the underlying MDnsDS daemon correctly discovers and resolves all nodes. However, the NsdService above does not propagate the resolution for all of them. There seems to be an ID conflict at 16:57:04.627, where both of the device's peers (TuSync-0.36230 and TuSync-0.60493) get assigned an internal ID of 107 (if I interpret the mechanisms correctly just by looking at the logs). The discoveryListener I registered with the NsdManager is notified upon the discovery of both nodes, however, resolving only works for one of them, the other triggers an error:

```<code>02-18 16:57:04.638: E/NsdHelper(6370): Resolve failed with error code:
3. Service: name: TuSync-0.60493, type: _tusync._tcp., host: null, port: 0
</code>```

I have also experienced additional cases where, after the NsdService emits a "SERVICE_FOUND Raw" message in the logs, my discovery listener is not notified. An exemplary log (heavily filtered; same test setup as above):

```<code>02-18 17:54:06.692: D/MDnsDS(187): Starting MDNSD
02-18 17:54:06.896: D/NsdService(628): registerService: 112 name: TuSync-0.57392, type: _tusync._tcp., host: /::, port: 57392
02-18 17:54:06.896: D/MDnsDS(187): serviceRegister(112, (null), TuSync-0.57392, _tusync._tcp., (null), (null), 57392, 0, <binary>)
02-18 17:54:06.896: D/MDnsDS(187): serviceRegister successful
02-18 17:54:08.802: D/NsdService(628): SERVICE_REGISTERED Raw: 606 112 "TuSync-0.57392"
02-18 17:54:08.820: D/NsdService(628): Discover services
02-18 17:54:09.050: D/MDnsDS(187): Discover found new serviceName TuSync-0.57392, regType _tusync._tcp. and domain local. for 113
02-18 17:54:09.050: D/NsdService(628): SERVICE_FOUND Raw: 603 113 "TuSync-0.57392" _tusync._tcp. local.
02-18 17:54:09.211: D/MDnsDS(187): Discover found new serviceName TuSync-0.60493, regType _tusync._tcp. and domain local. for 113
02-18 17:54:09.212: D/NsdService(628): SERVICE_FOUND Raw: 603 113 "TuSync-0.60493" _tusync._tcp. local.
02-18 17:54:09.215: D/NsdService(628): resolveService: 116 name: TuSync-0.60493, type: _tusync._tcp., host: null, port: 0
02-18 17:54:09.216: D/MDnsDS(187): resolveService(116, (null), TuSync-0.60493, _tusync._tcp., local.)
02-18 17:54:09.217: D/MDnsDS(187): resolve succeeded for 116 finding TuSync-0\.60493._tusync._tcp.local. at Android-2.local.:60493 with txtLen 1
02-18 17:54:09.219: D/NsdService(628): SERVICE_RESOLVED Raw: 608 116 "TuSync-0\\.60493._tusync._tcp.local." "Android-2.local." 60493 1
02-18 17:54:09.228: D/MDnsDS(187): getAddrInfo succeeded for 117: 117 "Android-2.local." 120 10.0.0.6
02-18 17:54:09.228: D/MDnsDS(187): getAddrInfo succeeded for 117: 117 "Android-2.local." 120 fe80::c643:8fff:fec5:5648
02-18 17:54:09.229: D/NsdService(628): SERVICE_GET_ADDR_SUCCESS Raw: 612 117 "Android-2.local." 120 10.0.0.6
02-18 17:54:09.244: D/MDnsDS(187): Discover found new serviceName TuSync-0.36230, regType _tusync._tcp. and domain local. for 113
02-18 17:54:09.251: E/NsdService(628): Unique id with no client mapping: 117
02-18 17:54:09.251: E/NsdService(628): Unhandled { when=-22ms what=393242 obj=com.android.server.NsdService$NativeEvent@1e992653 target=com.android.internal.util.StateMachine$SmHandler }
02-18 17:54:09.255: D/NsdService(628): SERVICE_FOUND Raw: 603 113 "TuSync-0.36230" _tusync._tcp. local.
</code>```

In this case, the discovered peer 10.0.0.5 (port 36230) triggers no discoveryListener notification. After the last log message, nothing happens. So my logging node 10.0.0.4 only discovered one other peer, 10.0.0.6:60493.

The low amount of similar bug reports makes me wonder if I'm the only one with these problems or if the NsdManager is completely unstable and no-one uses it anyway?

For reference, here is the code of my helper class - it is similar to the Android NSD chat tutorial, but I tried to improve it because of some other bugs the tutorial seems to provoke.

```<code>public final class NsdHelper {

    public static final String TAG = "NsdHelper";

    private final Context mContext;

    private final NsdManager mNsdManager;

    private final String mBaseServiceName; // Base component of the service name, e.g. "service_xy"
    private String mServiceName; // Service name of the local node, may be updated upon peer detection with service name conflicts, e.g. to "service_xy (2)"
    private final String mServiceType;

    private final NsdHandler mNsdHandler;

    private MyRegistrationListener mRegistrationListener;
    private final Object mRegistrationLock = new Object();

    private MyDiscoveryListener mDiscoveryListener;
    private final Object mDiscoveryLock = new Object();

    private final Object mResolveLock = new Object();
    private final Semaphore mResolveSemaphore;

    public NsdHelper(Context context, String baseServiceName, String serviceName, String serviceType, NsdHandler nsdHandler) {
        mContext = context;
        mNsdManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE);
        mNsdHandler = nsdHandler;
        mBaseServiceName = baseServiceName;
        mServiceName = serviceName;
        mServiceType = serviceType;

        mResolveSemaphore = new Semaphore(10, true);
    }

    /*********************
     * Lifecycle methods *
     *********************/

    public void registerLocalService(final int port) {

        NsdServiceInfo localServiceInfo = new NsdServiceInfo();
        localServiceInfo.setServiceName(mServiceName);
        localServiceInfo.setServiceType(mServiceType);
        localServiceInfo.setPort(port);

        synchronized (mRegistrationLock) {
            if (mRegistrationListener == null) {
                mRegistrationListener = new MyRegistrationListener();
                // try {
                mNsdManager.registerService(
                        localServiceInfo, NsdManager.PROTOCOL_DNS_SD, mRegistrationListener);

                /*} catch (Exception e) {
                    MLog.e(TAG, "Exception registering service; trying to unregister.", e);
                    unregisterLocalService();

                    mNsdHandler.onRegistrationFailed(localServiceInfo, 0);
                }*/
            } else {
                MLog.w(TAG, "registerLocalService called while service registration already in progress or service already registered.");
            }
        }
    }

    public void unregisterLocalService() {
        synchronized (mRegistrationLock) {
            if (mRegistrationListener != null) {
                // try {
                    mNsdManager.unregisterService(mRegistrationListener);
                /*} catch (IllegalArgumentException e) {
                    MLog.w(TAG, "Exception trying to unregister registrationListener.");
                }*/
                mRegistrationListener = null;
            } else {
                MLog.w(TAG, "unregisterLocalService called while service not yet registered or already unregistered.");
            }
        }
    }

    public void startDiscovery() {
        synchronized(mDiscoveryLock) {
            if(mDiscoveryListener == null) {
                mDiscoveryListener = new MyDiscoveryListener();
                mNsdManager.discoverServices(
                        mServiceType, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
            } else {
                MLog.w(TAG, "StartDiscovery called while discovery is already in progress.");
            }
        }
    }

    public void stopDiscovery() {
        synchronized (mDiscoveryLock) {
            if (mDiscoveryListener != null) {
                mNsdManager.stopServiceDiscovery(mDiscoveryListener);
                mDiscoveryListener = null;
            } else {
                MLog.w(TAG, "StopDiscovery called while no discovery is in progress.");
            }
        }
    }

    public void tearDown() {
        MLog.v(TAG, "NsdHelper: tearDown()");
        stopDiscovery();
        unregisterLocalService(); // TODO this causes an exception, when the listener is already unregistered
    }

    /**
     * Returns the current service name of the service.
     * @return
     */
    public String getServiceName() {
        return mServiceName;
    }

    /**
     * Convenience method to initiate service resolution
     * @param serviceInfo NsdServiceInfo object for the service to be resolved
     */
    private void resolveService(NsdServiceInfo serviceInfo) {
        try {
            MLog.vv(TAG, "Resolving service: acquiring semaphore.");
            mResolveSemaphore.acquire();
            MLog.vv(TAG, "Resolving service: semaphore acquired.");
        } catch (InterruptedException e) {
            MLog.w(TAG, "resolveService: Waiting for acquisition of semaphore interrupted.");
        }
        mNsdManager.resolveService(serviceInfo, new MyResolveListener(serviceInfo.getServiceName()));
    }

    /*************
     * Listeners *
     *************/

    private class MyDiscoveryListener implements NsdManager.DiscoveryListener {

        @Override
        public void onDiscoveryStarted(String regType) {
            MLog.d(TAG, "Service discovery started");
            mNsdHandler.onDiscoveryStarted();
        }

        @Override
        public void onServiceFound(NsdServiceInfo serviceInfo) {
            MLog.d(TAG, "Discovered service: " + serviceInfo);

            // Protocol matches?
            if (!serviceInfo.getServiceType().equals(mServiceType)) {
                MLog.v(TAG, "Discovered: other serviceType: " + serviceInfo.getServiceType());
            }
            // Make sure, that service name matches, and just resolve remote host
            else if (serviceInfo.getServiceName().contains(mBaseServiceName)){
                MLog.d(TAG, "Discovered: correct serviceType: " + mBaseServiceName);
                resolveService(serviceInfo);
            }
            else {
                // Other service name, log anyway
                MLog.d(TAG, "Discovered: service with different serviceName: " + serviceInfo.getServiceName() + ". Ignoring.");
            }
        }

        @Override
        public void onServiceLost(NsdServiceInfo service) {
            MLog.e(TAG, "Service lost: " + service);
            mNsdHandler.onRemotePeerLost(service);
        }

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

        @Override
        public void onStartDiscoveryFailed(String serviceType, int errorCode) {
            MLog.e(TAG, "Discovery starting failed. Error code: " + errorCode);
            synchronized (mDiscoveryLock) {
                mDiscoveryListener = null;  // just throw away the discovery listener, explicit stopping of the discovery should not be needed according to
                                            // https://code.google.com/p/android/issues/detail?id=99510&q=nsd&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars
            }
        }

        @Override
        public void onStopDiscoveryFailed(String serviceType, int errorCode) {
            MLog.e(TAG, "Discovery stopping failed. Error code: " + errorCode);
            // try again
            // mNsdManager.stopServiceDiscovery(this); // This should not be needed according to https://code.google.com/p/android/issues/detail?id=99510&q=nsd&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars
        }
    };

    private class MyRegistrationListener implements NsdManager.RegistrationListener {

        @Override
        public void onServiceRegistered(NsdServiceInfo nsdServiceInfo) {
            MLog.d(TAG, "Service registered. NsdServiceInfo: " + nsdServiceInfo);

            boolean nameChanged = false;

            // Update service name of this node (might change due to automatic conflict resolution!)
            if(!mServiceName.equals(nsdServiceInfo.getServiceName())){
                mServiceName = nsdServiceInfo.getServiceName();

                nameChanged = true;
                MLog.d(TAG, "Local service name updated to: " + mServiceName);
            }

            // Notify
            if (mNsdHandler != null) {
                mNsdHandler.onRegistrationSuccess(nsdServiceInfo);

                if (nameChanged) {
                mNsdHandler.onLocalServiceNameChanged(mServiceName);
                }
            } else {
                MLog.w(TAG, "onServiceRegistered: NsdHandler is null.");
            }
        }

        @Override
        public void onRegistrationFailed(NsdServiceInfo arg0, int arg1) {
            MLog.w(TAG, "Service registration failed with error code " + arg1 + ".");

            if (mNsdHandler == null) {
                MLog.w(TAG, "onRegistrationFailed: NsdHandler is null.");
                return;
            }

            mNsdHandler.onRegistrationFailed(arg0, arg1);
        }

        @Override
        public void onServiceUnregistered(NsdServiceInfo arg0) {
            MLog.d(TAG, "Service unregistered.");

            if (mNsdHandler == null) {
                MLog.w(TAG, "onServiceUnRegistered: NsdHandler is null.");
                return;
            }
        }

        @Override
        public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
            MLog.w(TAG, "Service unregistering failed.");

            if (mNsdHandler == null) {
                MLog.w(TAG, "onUnRegistrationFailed: NsdHandler is null.");
                return;
            }
        }

    };

    private class MyResolveListener implements NsdManager.ResolveListener {

        private final String mServiceName;

        public MyResolveListener(String serviceName) {
            mServiceName = serviceName;
        }

        @Override
        public void onResolveFailed(final NsdServiceInfo serviceInfo, int errorCode) {
            // Release resource
            mResolveSemaphore.release();

            MLog.e(TAG, "Resolve failed with error code: " + errorCode + ". Service: " + serviceInfo);
            if((serviceInfo.getServiceName() != null) && (!serviceInfo.getServiceName().equals(mServiceName))) {
                MLog.e(TAG, "Service name changed: " + mServiceName + " => " + serviceInfo.getServiceName());
            }
        }

        @Override
        public void onServiceResolved(final NsdServiceInfo serviceInfo) {
            // Release resource
            mResolveSemaphore.release();

            MLog.v(TAG, "Resolve succeeded. Service: " + serviceInfo + ", Address: " + serviceInfo.getHost().getHostAddress() + ":" + serviceInfo.getPort());
            if((serviceInfo.getServiceName() != null) && (!serviceInfo.getServiceName().equals(mServiceName))) {
                MLog.w(TAG, "Service name changed: " + mServiceName + " => " + serviceInfo.getServiceName());
            }

            mNsdHandler.onNewRemotePeerResolved(serviceInfo);
        }
    };

    /**
     * Interface for handlers that deal just with essential NSD events.
     * @author Alexander Fischl (alexander.fischl@semeion.net)
     */
    public interface NsdHandler {

        /**
         * Called, when the NSD manager registered the service successfully.
         * @param nsdServiceInfo
         */
        public void onRegistrationSuccess(final NsdServiceInfo nsdServiceInfo);

        /**
         * Called, when the NSD registration was unsuccessful.
         */
        public void onRegistrationFailed(final NsdServiceInfo nsdServiceInfo, final int errorCode);

        /**
         * Called, when the NSD manager discovers a new peer. Services registered on the
         * local machine DO NOT trigger this call!
         * @param nsdServiceInfo
         */
        public void onNewRemotePeerDiscovered(final NsdServiceInfo nsdServiceInfo);

        /**
         * Called, when the NSD manager resolves a new peer, yielding the connection data.
         * Services registered on the local machine DO NOT trigger this call!
         * @param nsdServiceInfo
         */
        public void onNewRemotePeerResolved(final NsdServiceInfo nsdServiceInfo);

        /**
         * Called, when the NSD manager loses an already discovered peer.
         * @param nsdServiceInfo
         */
        public void onRemotePeerLost(final NsdServiceInfo nsdServiceInfo);

        /**
         * Called, when the local service name needs to be updated (e.g. due to
         * conflict resolution when the local service is registered, and the chosen service
         * name is already taken by another node in the network.)
         * @param newLocalServiceName
         */
        public void onLocalServiceNameChanged(String newLocalServiceName);

        /**
         * Called, when the service discovery has successfully started.
         */
        public void onDiscoveryStarted();

        /**
         * Called, when the service discovery was halted.
         */
        public void onDiscoveryStopped();
    }
}
</code>```

Note, that I even implemented a semaphore that can be set to 1 to prevent resolving multiple services in parallel, as somebody else reported problems with parallel resolution. However, setting it to 1 does not work, as sometimes the ongoing resolution does neither succeed nor fail; which causes the semaphore not to be released and the NsdManager thread to get permanently stuck at the next resolve request.

Is anyone else experiencing such problems? I'd be glad if also people who are successfully employing the NsdManager would comment - that would at least mean I'm facing a problem I can fix :)

I already considered giving up on NSD and implementing my own broadcast/multicast discovery mechanism. This could theoretically be a breeze, but I've read that multicast on Android is a PITA too, because of some devices preventing it...

答:
Still no difference with Android NSD. I had been using Marshmallow version of Android and NSD actually is still unreliable. I replaced the NSD with  RxDNSSD ( https://github.com/andriydruk/RxDNSSD ). Few liner code works perfect till now.

I tested NSD & RXDNSSD, NSD was able to discover service but not able to resolve IP address while RXDNSSD was working all the time.

Hope it will help for other users.

Body:
In the course of the last weeks, Android's NSD implementation is making me go mad:

From a user's point of view, the following problems arise:

Devices discover each other in a completely non-deterministic fashion. If I launch my NsdManager-based app, it works more or less if only two devices are involved. If a third device joins, it will seldomly discover the first two, and the first two will not see the third. If I exit the apps (they gracefully unregister the NSD listeners) and restart them in a different order, the discovery pattern is not exactly the same, but similar.

In my home network, the IP resolution of the discovered devices basically works as expected. At work, sometimes even when only using two devices (A and B), device A will resolve device B's service with A's IP address and B's port and vice-versa. So somehow the IP address and service name seem to get mixed up at a lower level (probably the NsdManager).

I've now filed a bug report on Google code for this (https://code.google.com/p/android/issues/detail?id=201314&thanks=201314&ts=1455814995). I'm posting this here too in hope to get more feedback; maybe I got something in my Nsd helper class wrong.

First of all, after endless debugging, I have now found hints in the logcat that Android's underlying NsdService itself might be malfunctioning, while MDnsDS seems to work correctly. But I'm unsure...

Here's some log output that illustrates the problem (some messages filtered for readability):

02-18 16:57:02.327: D/NsdService(628): startMDnsDaemon
02-18 16:57:02.327: D/MDnsDS(187): Starting MDNSD
02-18 16:57:02.529: D/NsdService(628): New client listening to asynchronous messages
02-18 16:57:02.529: D/NsdService(628): New client, channel: com.android.internal.util.AsyncChannel@1fa188ce messenger: android.os.Messenger@cca33ef
02-18 16:57:02.532: D/NsdService(628): Register service
02-18 16:57:02.532: D/NsdService(628): registerService: 106 name: TuSync-0.57392, type: _tusync._tcp., host: /::, port: 57392
02-18 16:57:02.533: D/MDnsDS(187): serviceRegister(106, (null), TuSync-0.57392, _tusync._tcp., (null), (null), 57392, 0, <binary>)
02-18 16:57:02.533: D/MDnsDS(187): serviceRegister successful
02-18 16:57:02.534: D/NsdService(628): Register 1 106
02-18 16:57:04.083: D/MDnsDS(187): register succeeded for 106 as TuSync-0.57392
02-18 16:57:04.087: D/NsdService(628): SERVICE_REGISTERED Raw: 606 106 "TuSync-0.57392"
02-18 16:57:04.109: D/NsdService(628): Discover services
02-18 16:57:04.109: D/NsdService(628): discoverServices: 107 _tusync._tcp.
02-18 16:57:04.110: D/MDnsDS(187): discover((null), _tusync._tcp., (null), 107, 0)
02-18 16:57:04.110: D/MDnsDS(187): discover successful
02-18 16:57:04.110: D/NsdService(628): Discover 2 107_tusync._tcp.
02-18 16:57:04.333: D/MDnsDS(187): Discover found new serviceName TuSync-0.57392, regType _tusync._tcp. and domain local. for 107
02-18 16:57:04.334: D/NsdService(628): SERVICE_FOUND Raw: 603 107 "TuSync-0.57392" _tusync._tcp. local.
02-18 16:57:04.338: D/NsdService(628): Resolve service
02-18 16:57:04.338: D/NsdService(628): resolveService: 108 name: TuSync-0.57392, type: _tusync._tcp., host: null, port: 0
02-18 16:57:04.339: D/MDnsDS(187): resolveService(108, (null), TuSync-0.57392, _tusync._tcp., local.)
02-18 16:57:04.345: D/MDnsDS(187): startMonitoring 108
02-18 16:57:04.345: D/MDnsDS(187): resolveService successful
02-18 16:57:04.346: D/MDnsDS(187): resolve succeeded for 108 finding TuSync-0\.57392._tusync._tcp.local. at Android-3.local.:57392 with txtLen 1
02-18 16:57:04.347: D/NsdService(628): SERVICE_RESOLVED Raw: 608 108 "TuSync-0\\.57392._tusync._tcp.local." "Android-3.local." 57392 1
02-18 16:57:04.347: D/NsdService(628): stopResolveService: 108
02-18 16:57:04.347: D/MDnsDS(187): Stopping resolve with ref 0xb5c4734c
02-18 16:57:04.349: D/NsdService(628): getAdddrInfo: 109
02-18 16:57:04.349: D/MDnsDS(187): getAddrInfo(109, (null) 0, Android-3.local.)
02-18 16:57:04.350: D/MDnsDS(187): getAddrInfo successful
02-18 16:57:04.352: D/MDnsDS(187): getAddrInfo succeeded for 109: 109 "Android-3.local." 120 10.0.0.4
02-18 16:57:04.352: D/MDnsDS(187): getAddrInfo succeeded for 109: 109 "Android-3.local." 120 fe80::204:4bff:fe2c:6c87
02-18 16:57:04.354: D/NsdService(628): SERVICE_GET_ADDR_SUCCESS Raw: 612 109 "Android-3.local." 120 10.0.0.4
02-18 16:57:04.354: D/NsdService(628): stopGetAdddrInfo: 109
02-18 16:57:04.355: D/MDnsDS(187): Stopping getaddrinfo with ref 0xb5c472d4
02-18 16:57:04.364: E/NsdService(628): Unique id with no client mapping: 109
02-18 16:57:04.364: E/NsdService(628): Unhandled { when=-10ms what=393242 obj=com.android.server.NsdService$NativeEvent@86af300 target=com.android.internal.util.StateMachine$SmHandler }
02-18 16:57:04.627: D/MDnsDS(187): Discover found new serviceName TuSync-0.36230, regType _tusync._tcp. and domain local. for 107
02-18 16:57:04.632: D/MDnsDS(187): Discover found new serviceName TuSync-0.60493, regType _tusync._tcp. and domain local. for 107
02-18 16:57:04.633: D/NsdService(628): SERVICE_FOUND Raw: 603 107 "TuSync-0.36230" _tusync._tcp. local.
02-18 16:57:04.634: D/NsdService(628): SERVICE_FOUND Raw: 603 107 "TuSync-0.60493" _tusync._tcp. local.
02-18 16:57:04.635: D/NsdService(628): Resolve service
02-18 16:57:04.635: D/NsdService(628): resolveService: 110 name: TuSync-0.36230, type: _tusync._tcp., host: null, port: 0
02-18 16:57:04.636: D/MDnsDS(187): resolveService(110, (null), TuSync-0.36230, _tusync._tcp., local.)
02-18 16:57:04.637: D/MDnsDS(187): resolve succeeded for 110 finding TuSync-0\.36230._tusync._tcp.local. at Android.local.:36230 with txtLen 1
02-18 16:57:04.638: D/NsdService(628): Resolve service
02-18 16:57:04.638: D/NsdService(628): SERVICE_RESOLVED Raw: 608 110 "TuSync-0\\.36230._tusync._tcp.local." "Android.local." 36230 1
02-18 16:57:04.639: D/NsdService(628): stopResolveService: 110
02-18 16:57:04.639: D/MDnsDS(187): Stopping resolve with ref 0xb5c473c4
02-18 16:57:04.643: D/MDnsDS(187): getAddrInfo succeeded for 111: 111 "Android.local." 120 10.0.0.5
02-18 16:57:04.643: D/MDnsDS(187): getAddrInfo succeeded for 111: 111 "Android.local." 120 fe80::204:4bff:fe26:8483
02-18 16:57:04.644: D/NsdService(628): SERVICE_GET_ADDR_SUCCESS Raw: 612 111 "Android.local." 120 10.0.0.5
02-18 16:57:04.644: D/NsdService(628): stopGetAdddrInfo: 111
02-18 16:57:04.645: D/MDnsDS(187): Stopping getaddrinfo with ref 0xb5c47364
02-18 16:57:04.645: D/MDnsDS(187): Going to poll with pollCount 3
02-18 16:57:04.658: E/NsdService(628): Unique id with no client mapping: 111
02-18 16:57:04.658: E/NsdService(628): Unhandled { when=-14ms what=393242 obj=com.android.server.NsdService$NativeEvent@1d93a739 target=com.android.internal.util.StateMachine$SmHandler }

Some notes on the context:

My NSD service type is _tusync._tcp.

I create unique service names for all nodes in the format TuSync-0.[local port number] to prevent naming conflicts and ease debugging.

In this test scenario, there are three devices. The logging device's IP is 10.0.0.4, port 57392.

The log shows, that the underlying MDnsDS daemon correctly discovers and resolves all nodes. However, the NsdService above does not propagate the resolution for all of them. There seems to be an ID conflict at 16:57:04.627, where both of the device's peers (TuSync-0.36230 and TuSync-0.60493) get assigned an internal ID of 107 (if I interpret the mechanisms correctly just by looking at the logs). The discoveryListener I registered with the NsdManager is notified upon the discovery of both nodes, however, resolving only works for one of them, the other triggers an error:

02-18 16:57:04.638: E/NsdHelper(6370): Resolve failed with error code:
3. Service: name: TuSync-0.60493, type: _tusync._tcp., host: null, port: 0

I have also experienced additional cases where, after the NsdService emits a "SERVICE_FOUND Raw" message in the logs, my discovery listener is not notified. An exemplary log (heavily filtered; same test setup as above):

02-18 17:54:06.692: D/MDnsDS(187): Starting MDNSD
02-18 17:54:06.896: D/NsdService(628): registerService: 112 name: TuSync-0.57392, type: _tusync._tcp., host: /::, port: 57392
02-18 17:54:06.896: D/MDnsDS(187): serviceRegister(112, (null), TuSync-0.57392, _tusync._tcp., (null), (null), 57392, 0, <binary>)
02-18 17:54:06.896: D/MDnsDS(187): serviceRegister successful
02-18 17:54:08.802: D/NsdService(628): SERVICE_REGISTERED Raw: 606 112 "TuSync-0.57392"
02-18 17:54:08.820: D/NsdService(628): Discover services
02-18 17:54:09.050: D/MDnsDS(187): Discover found new serviceName TuSync-0.57392, regType _tusync._tcp. and domain local. for 113
02-18 17:54:09.050: D/NsdService(628): SERVICE_FOUND Raw: 603 113 "TuSync-0.57392" _tusync._tcp. local.
02-18 17:54:09.211: D/MDnsDS(187): Discover found new serviceName TuSync-0.60493, regType _tusync._tcp. and domain local. for 113
02-18 17:54:09.212: D/NsdService(628): SERVICE_FOUND Raw: 603 113 "TuSync-0.60493" _tusync._tcp. local.
02-18 17:54:09.215: D/NsdService(628): resolveService: 116 name: TuSync-0.60493, type: _tusync._tcp., host: null, port: 0
02-18 17:54:09.216: D/MDnsDS(187): resolveService(116, (null), TuSync-0.60493, _tusync._tcp., local.)
02-18 17:54:09.217: D/MDnsDS(187): resolve succeeded for 116 finding TuSync-0\.60493._tusync._tcp.local. at Android-2.local.:60493 with txtLen 1
02-18 17:54:09.219: D/NsdService(628): SERVICE_RESOLVED Raw: 608 116 "TuSync-0\\.60493._tusync._tcp.local." "Android-2.local." 60493 1
02-18 17:54:09.228: D/MDnsDS(187): getAddrInfo succeeded for 117: 117 "Android-2.local." 120 10.0.0.6
02-18 17:54:09.228: D/MDnsDS(187): getAddrInfo succeeded for 117: 117 "Android-2.local." 120 fe80::c643:8fff:fec5:5648
02-18 17:54:09.229: D/NsdService(628): SERVICE_GET_ADDR_SUCCESS Raw: 612 117 "Android-2.local." 120 10.0.0.6
02-18 17:54:09.244: D/MDnsDS(187): Discover found new serviceName TuSync-0.36230, regType _tusync._tcp. and domain local. for 113
02-18 17:54:09.251: E/NsdService(628): Unique id with no client mapping: 117
02-18 17:54:09.251: E/NsdService(628): Unhandled { when=-22ms what=393242 obj=com.android.server.NsdService$NativeEvent@1e992653 target=com.android.internal.util.StateMachine$SmHandler }
02-18 17:54:09.255: D/NsdService(628): SERVICE_FOUND Raw: 603 113 "TuSync-0.36230" _tusync._tcp. local.

In this case, the discovered peer 10.0.0.5 (port 36230) triggers no discoveryListener notification. After the last log message, nothing happens. So my logging node 10.0.0.4 only discovered one other peer, 10.0.0.6:60493.

The low amount of similar bug reports makes me wonder if I'm the only one with these problems or if the NsdManager is completely unstable and no-one uses it anyway?

For reference, here is the code of my helper class - it is similar to the Android NSD chat tutorial, but I tried to improve it because of some other bugs the tutorial seems to provoke.

public final class NsdHelper {

    public static final String TAG = "NsdHelper";

    private final Context mContext;

    private final NsdManager mNsdManager;

    private final String mBaseServiceName; // Base component of the service name, e.g. "service_xy"
    private String mServiceName; // Service name of the local node, may be updated upon peer detection with service name conflicts, e.g. to "service_xy (2)"
    private final String mServiceType;

    private final NsdHandler mNsdHandler;

    private MyRegistrationListener mRegistrationListener;
    private final Object mRegistrationLock = new Object();

    private MyDiscoveryListener mDiscoveryListener;
    private final Object mDiscoveryLock = new Object();

    private final Object mResolveLock = new Object();
    private final Semaphore mResolveSemaphore;

    public NsdHelper(Context context, String baseServiceName, String serviceName, String serviceType, NsdHandler nsdHandler) {
        mContext = context;
        mNsdManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE);
        mNsdHandler = nsdHandler;
        mBaseServiceName = baseServiceName;
        mServiceName = serviceName;
        mServiceType = serviceType;

        mResolveSemaphore = new Semaphore(10, true);
    }

    /*********************
     * Lifecycle methods *
     *********************/

    public void registerLocalService(final int port) {

        NsdServiceInfo localServiceInfo = new NsdServiceInfo();
        localServiceInfo.setServiceName(mServiceName);
        localServiceInfo.setServiceType(mServiceType);
        localServiceInfo.setPort(port);

        synchronized (mRegistrationLock) {
            if (mRegistrationListener == null) {
                mRegistrationListener = new MyRegistrationListener();
                // try {
                mNsdManager.registerService(
                        localServiceInfo, NsdManager.PROTOCOL_DNS_SD, mRegistrationListener);

                /*} catch (Exception e) {
                    MLog.e(TAG, "Exception registering service; trying to unregister.", e);
                    unregisterLocalService();

                    mNsdHandler.onRegistrationFailed(localServiceInfo, 0);
                }*/
            } else {
                MLog.w(TAG, "registerLocalService called while service registration already in progress or service already registered.");
            }
        }
    }

    public void unregisterLocalService() {
        synchronized (mRegistrationLock) {
            if (mRegistrationListener != null) {
                // try {
                    mNsdManager.unregisterService(mRegistrationListener);
                /*} catch (IllegalArgumentException e) {
                    MLog.w(TAG, "Exception trying to unregister registrationListener.");
                }*/
                mRegistrationListener = null;
            } else {
                MLog.w(TAG, "unregisterLocalService called while service not yet registered or already unregistered.");
            }
        }
    }

    public void startDiscovery() {
        synchronized(mDiscoveryLock) {
            if(mDiscoveryListener == null) {
                mDiscoveryListener = new MyDiscoveryListener();
                mNsdManager.discoverServices(
                        mServiceType, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
            } else {
                MLog.w(TAG, "StartDiscovery called while discovery is already in progress.");
            }
        }
    }

    public void stopDiscovery() {
        synchronized (mDiscoveryLock) {
            if (mDiscoveryListener != null) {
                mNsdManager.stopServiceDiscovery(mDiscoveryListener);
                mDiscoveryListener = null;
            } else {
                MLog.w(TAG, "StopDiscovery called while no discovery is in progress.");
            }
        }
    }

    public void tearDown() {
        MLog.v(TAG, "NsdHelper: tearDown()");
        stopDiscovery();
        unregisterLocalService(); // TODO this causes an exception, when the listener is already unregistered
    }

    /**
     * Returns the current service name of the service.
     * @return
     */
    public String getServiceName() {
        return mServiceName;
    }

    /**
     * Convenience method to initiate service resolution
     * @param serviceInfo NsdServiceInfo object for the service to be resolved
     */
    private void resolveService(NsdServiceInfo serviceInfo) {
        try {
            MLog.vv(TAG, "Resolving service: acquiring semaphore.");
            mResolveSemaphore.acquire();
            MLog.vv(TAG, "Resolving service: semaphore acquired.");
        } catch (InterruptedException e) {
            MLog.w(TAG, "resolveService: Waiting for acquisition of semaphore interrupted.");
        }
        mNsdManager.resolveService(serviceInfo, new MyResolveListener(serviceInfo.getServiceName()));
    }

    /*************
     * Listeners *
     *************/

    private class MyDiscoveryListener implements NsdManager.DiscoveryListener {

        @Override
        public void onDiscoveryStarted(String regType) {
            MLog.d(TAG, "Service discovery started");
            mNsdHandler.onDiscoveryStarted();
        }

        @Override
        public void onServiceFound(NsdServiceInfo serviceInfo) {
            MLog.d(TAG, "Discovered service: " + serviceInfo);

            // Protocol matches?
            if (!serviceInfo.getServiceType().equals(mServiceType)) {
                MLog.v(TAG, "Discovered: other serviceType: " + serviceInfo.getServiceType());
            }
            // Make sure, that service name matches, and just resolve remote host
            else if (serviceInfo.getServiceName().contains(mBaseServiceName)){
                MLog.d(TAG, "Discovered: correct serviceType: " + mBaseServiceName);
                resolveService(serviceInfo);
            }
            else {
                // Other service name, log anyway
                MLog.d(TAG, "Discovered: service with different serviceName: " + serviceInfo.getServiceName() + ". Ignoring.");
            }
        }

        @Override
        public void onServiceLost(NsdServiceInfo service) {
            MLog.e(TAG, "Service lost: " + service);
            mNsdHandler.onRemotePeerLost(service);
        }

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

        @Override
        public void onStartDiscoveryFailed(String serviceType, int errorCode) {
            MLog.e(TAG, "Discovery starting failed. Error code: " + errorCode);
            synchronized (mDiscoveryLock) {
                mDiscoveryListener = null;  // just throw away the discovery listener, explicit stopping of the discovery should not be needed according to
                                            // https://code.google.com/p/android/issues/detail?id=99510&q=nsd&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars
            }
        }

        @Override
        public void onStopDiscoveryFailed(String serviceType, int errorCode) {
            MLog.e(TAG, "Discovery stopping failed. Error code: " + errorCode);
            // try again
            // mNsdManager.stopServiceDiscovery(this); // This should not be needed according to https://code.google.com/p/android/issues/detail?id=99510&q=nsd&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars
        }
    };

    private class MyRegistrationListener implements NsdManager.RegistrationListener {

        @Override
        public void onServiceRegistered(NsdServiceInfo nsdServiceInfo) {
            MLog.d(TAG, "Service registered. NsdServiceInfo: " + nsdServiceInfo);

            boolean nameChanged = false;

            // Update service name of this node (might change due to automatic conflict resolution!)
            if(!mServiceName.equals(nsdServiceInfo.getServiceName())){
                mServiceName = nsdServiceInfo.getServiceName();

                nameChanged = true;
                MLog.d(TAG, "Local service name updated to: " + mServiceName);
            }

            // Notify
            if (mNsdHandler != null) {
                mNsdHandler.onRegistrationSuccess(nsdServiceInfo);

                if (nameChanged) {
                mNsdHandler.onLocalServiceNameChanged(mServiceName);
                }
            } else {
                MLog.w(TAG, "onServiceRegistered: NsdHandler is null.");
            }
        }

        @Override
        public void onRegistrationFailed(NsdServiceInfo arg0, int arg1) {
            MLog.w(TAG, "Service registration failed with error code " + arg1 + ".");

            if (mNsdHandler == null) {
                MLog.w(TAG, "onRegistrationFailed: NsdHandler is null.");
                return;
            }

            mNsdHandler.onRegistrationFailed(arg0, arg1);
        }

        @Override
        public void onServiceUnregistered(NsdServiceInfo arg0) {
            MLog.d(TAG, "Service unregistered.");

            if (mNsdHandler == null) {
                MLog.w(TAG, "onServiceUnRegistered: NsdHandler is null.");
                return;
            }
        }

        @Override
        public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
            MLog.w(TAG, "Service unregistering failed.");

            if (mNsdHandler == null) {
                MLog.w(TAG, "onUnRegistrationFailed: NsdHandler is null.");
                return;
            }
        }

    };

    private class MyResolveListener implements NsdManager.ResolveListener {

        private final String mServiceName;

        public MyResolveListener(String serviceName) {
            mServiceName = serviceName;
        }

        @Override
        public void onResolveFailed(final NsdServiceInfo serviceInfo, int errorCode) {
            // Release resource
            mResolveSemaphore.release();

            MLog.e(TAG, "Resolve failed with error code: " + errorCode + ". Service: " + serviceInfo);
            if((serviceInfo.getServiceName() != null) && (!serviceInfo.getServiceName().equals(mServiceName))) {
                MLog.e(TAG, "Service name changed: " + mServiceName + " => " + serviceInfo.getServiceName());
            }
        }

        @Override
        public void onServiceResolved(final NsdServiceInfo serviceInfo) {
            // Release resource
            mResolveSemaphore.release();

            MLog.v(TAG, "Resolve succeeded. Service: " + serviceInfo + ", Address: " + serviceInfo.getHost().getHostAddress() + ":" + serviceInfo.getPort());
            if((serviceInfo.getServiceName() != null) && (!serviceInfo.getServiceName().equals(mServiceName))) {
                MLog.w(TAG, "Service name changed: " + mServiceName + " => " + serviceInfo.getServiceName());
            }

            mNsdHandler.onNewRemotePeerResolved(serviceInfo);
        }
    };

    /**
     * Interface for handlers that deal just with essential NSD events.
     * @author Alexander Fischl (alexander.fischl@semeion.net)
     */
    public interface NsdHandler {

        /**
         * Called, when the NSD manager registered the service successfully.
         * @param nsdServiceInfo
         */
        public void onRegistrationSuccess(final NsdServiceInfo nsdServiceInfo);

        /**
         * Called, when the NSD registration was unsuccessful.
         */
        public void onRegistrationFailed(final NsdServiceInfo nsdServiceInfo, final int errorCode);

        /**
         * Called, when the NSD manager discovers a new peer. Services registered on the
         * local machine DO NOT trigger this call!
         * @param nsdServiceInfo
         */
        public void onNewRemotePeerDiscovered(final NsdServiceInfo nsdServiceInfo);

        /**
         * Called, when the NSD manager resolves a new peer, yielding the connection data.
         * Services registered on the local machine DO NOT trigger this call!
         * @param nsdServiceInfo
         */
        public void onNewRemotePeerResolved(final NsdServiceInfo nsdServiceInfo);

        /**
         * Called, when the NSD manager loses an already discovered peer.
         * @param nsdServiceInfo
         */
        public void onRemotePeerLost(final NsdServiceInfo nsdServiceInfo);

        /**
         * Called, when the local service name needs to be updated (e.g. due to
         * conflict resolution when the local service is registered, and the chosen service
         * name is already taken by another node in the network.)
         * @param newLocalServiceName
         */
        public void onLocalServiceNameChanged(String newLocalServiceName);

        /**
         * Called, when the service discovery has successfully started.
         */
        public void onDiscoveryStarted();

        /**
         * Called, when the service discovery was halted.
         */
        public void onDiscoveryStopped();
    }
}

Note, that I even implemented a semaphore that can be set to 1 to prevent resolving multiple services in parallel, as somebody else reported problems with parallel resolution. However, setting it to 1 does not work, as sometimes the ongoing resolution does neither succeed nor fail; which causes the semaphore not to be released and the NsdManager thread to get permanently stuck at the next resolve request.

Is anyone else experiencing such problems? I'd be glad if also people who are successfully employing the NsdManager would comment - that would at least mean I'm facing a problem I can fix :)

I already considered giving up on NSD and implementing my own broadcast/multicast discovery mechanism. This could theoretically be a breeze, but I've read that multicast on Android is a PITA too, because of some devices preventing it...


来源: stackexchange

问:
Tm.plugin.webmining in R - Google News feeds
I am trying to learn text mining in R.

I am encountering problems when it comes to using the tm.plugin.webmining package when trying to mine google news and finance pages (please see codes and error messages attached below).

I would appreciate any help I can get.

Using GoogleNewsSource

```<code>googlenews <- WebCorpus(GoogleNewsSource("Microsoft"))
Unknown IO errorfailed to load external entity "http://news.google.com/news?hl=en&q=Microsoft&ie=utf-8&num=100&output=rss"
Error: 1: Unknown IO error2: failed to load external entity "http://news.google.com/news?hl=en&q=Microsoft&ie=utf-8&num=100&output=rss"

library(tm.plugin.webmining)
library(purrr)

company <- c("Microsoft", "Apple", "Google", "Amazon", "Facebook",
             "Twitter", "IBM", "Yahoo", "Netflix")
symbol <- c("MSFT", "AAPL", "GOOG", "AMZN", "FB", "TWTR", "IBM", "YHOO", "NFLX")

download_articles <- function(symbol) {
  WebCorpus(GoogleFinanceSource(paste0("NASDAQ:", symbol)))
}

stock_articles <- data_frame(company = company,
                             symbol = symbol) %>%
  mutate(corpus = map(symbol, download_articles))
failed to load HTTP resource
Error in mutate_impl(.data, dots) : 1: failed to load HTTP resource
</code>```

答:
The problem is in the NASDAQ:TWTR. Removing both "Twitter" from the company and "TWTR" from the symbol resolves the error.

```<code>company <- c("Microsoft", "Apple", "Google", "Amazon", "Facebook", "Netflix")
symbol <- c("MSFT", "AAPL", "GOOG", "AMZN", "FB", "NFLX")

download_articles <- function(symbol) {
  WebCorpus(GoogleFinanceSource(paste0("NASDAQ:", symbol)))
}
stock_articles <- data_frame(company = company,
                             symbol = symbol) %>%
  mutate(corpus = map(symbol, download_articles))
stock_articles
#     # A tibble: 6 x 3
#     company symbol          corpus
#       <chr>  <chr>          <list>
# 1 Microsoft   MSFT <S3: WebCorpus>
# 2     Apple   AAPL <S3: WebCorpus>
# 3    Google   GOOG <S3: WebCorpus>
# 4    Amazon   AMZN <S3: WebCorpus>
# 5  Facebook     FB <S3: WebCorpus>
# 6   Netflix   NFLX <S3: WebCorpus>
</code>```

ContentLicense: CC BY-SA 3.0

Body:
I am trying to learn text mining in R.

I am encountering problems when it comes to using the tm.plugin.webmining package when trying to mine google news and finance pages (please see codes and error messages attached below).

I would appreciate any help I can get.

Using GoogleNewsSource

googlenews <- WebCorpus(GoogleNewsSource("Microsoft"))
Unknown IO errorfailed to load external entity "http://news.google.com/news?hl=en&q=Microsoft&ie=utf-8&num=100&output=rss"
Error: 1: Unknown IO error2: failed to load external entity "http://news.google.com/news?hl=en&q=Microsoft&ie=utf-8&num=100&output=rss"

library(tm.plugin.webmining)
library(purrr)

company <- c("Microsoft", "Apple", "Google", "Amazon", "Facebook",
             "Twitter", "IBM", "Yahoo", "Netflix")
symbol <- c("MSFT", "AAPL", "GOOG", "AMZN", "FB", "TWTR", "IBM", "YHOO", "NFLX")

download_articles <- function(symbol) {
  WebCorpus(GoogleFinanceSource(paste0("NASDAQ:", symbol)))
}

stock_articles <- data_frame(company = company,
                             symbol = symbol) %>%
  mutate(corpus = map(symbol, download_articles))
failed to load HTTP resource
Error in mutate_impl(.data, dots) : 1: failed to load HTTP resource

Body:
The problem is in the NASDAQ:TWTR. Removing both "Twitter" from the company and "TWTR" from the symbol resolves the error.

company <- c("Microsoft", "Apple", "Google", "Amazon", "Facebook", "Netflix")
symbol <- c("MSFT", "AAPL", "GOOG", "AMZN", "FB", "NFLX")

download_articles <- function(symbol) {
  WebCorpus(GoogleFinanceSource(paste0("NASDAQ:", symbol)))
}
stock_articles <- data_frame(company = company,
                             symbol = symbol) %>%
  mutate(corpus = map(symbol, download_articles))
stock_articles
#     # A tibble: 6 x 3
#     company symbol          corpus
#       <chr>  <chr>          <list>
# 1 Microsoft   MSFT <S3: WebCorpus>
# 2     Apple   AAPL <S3: WebCorpus>
# 3    Google   GOOG <S3: WebCorpus>
# 4    Amazon   AMZN <S3: WebCorpus>
# 5  Facebook     FB <S3: WebCorpus>
# 6   Netflix   NFLX <S3: WebCorpus>


问:
Is using __cplusplus undefined behaviour in C?
Modern C++ compilers are required by the standard to #define the macro __cplusplus.

This is often used in files that can be used by both C and C++ but the implementation differs slightly.

But in C (and C++ for that matter), the behaviour on using any double underscore in an identifier is undefined!

So therefore, if a C compiler sees something like

#ifdef __cplusplus

then is the behaviour undefined?

答:
The corresponding part from the standard is(emphasis mine):

7.1.3 Reserved identifiers

1
Each header declares or defines all identifiers listed in its associated subclause, and optionally declares or defines identifiers listed in its associated future library directions subclause and identifiers which are always reserved either for any use or for use as file scope identifiers.

So a little bit contrary to what Ven posted, this is an implicit requirement to not use them at all, since they are also reserved for future purposes.

This is also stated more strict under section 2 of 7.1.3:

No other identifiers are reserved. If the program declares or defines an identifier in a context in which it is reserved (other than as allowed by 7.1.4), or defines a reserved identifier as a macro name, the behavior is undefined.

So they are strictly reserved for future implementations, which for example __cplusplus is making use of, as the first rule that defines what is reserved states:

— All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use.

But since your example is implemented by the standard by using an identifier from that mentioned reserved spectrum it is fine.

Additionally the example you are giving is actually not declaring/defining an identifier but checking if there is a preprocessing token(macro) is defined with the name __cplusplus what would be totally ok by means of the C standard aswell, since its checking if it exists, not declaring anything.
If you would have defined it your self, it would be not strictly respecting the C standard and cause possible undefined behavior.


问:
PHP => $_SESSION Array only keeps last variable
I'm building an interface for an online shop, where every item is a FORM and the BUY button is a submit,it submits the name and price of the clicked form and that data is displayed on a CONFIRM ORDER page. On that confirm order page I've created an array as follows

```<code>if (!isset($input_order_arr)) {
  $input_order_arr = array();
}
</code>```

After that I fetch the posted variables and push them into the array

```<code>if ($_SERVER['REQUEST_METHOD'] == 'POST') {
  if (!empty($_POST['item-title'])  && !empty($_POST['item-price'])) {
    $item_title = test_input($_POST['item-title']);
    $item_price = test_input($_POST['item-price']);
    array_push($input_order_arr,$item_title,$item_price);
  }
}

$_SESSION['chosen_item'] = $input_order_arr;
</code>```

*NOTE : test_input is a function that does striplashes , htmlspecialchars and htmltrim, for security purposes. (someone might edit the value of the item via the Chrome developer console? not sure if that holds any threat though)

And after that the value is displayed in a table like so

```<code>              <?php if (isset($_SESSION['chosen_item'])) {
                foreach ($_SESSION['chosen_item'] as $value) {
                  echo "<td>" . $value . "</td>";
                }
              }  ?>
</code>```

And here comes the problem.

If you order an item its price and name are displayed, but if u go back and you order another item, the previous item and its price are lost, as if its not adding new lines to the array,but replacing the old ones, or the session only saves data from one action, which wouldn't make any sense, since thats what $_SESSION is about, the code is presented with session_start(); in every page that is using the $_SESSION variable.

 Main Question - Why could it be that the $_SESSION Array is losing its older inputs?

答:
When you go back, you basically are setting the chosen_item array element to empty, since $input_order_arr would not contain anything when you haven't submitted a form.

You should append to the session array only if there is a nonempty $input_order_arr array:

```<code>if ($_SERVER['REQUEST_METHOD'] == 'POST') {
  if (!empty($_POST['item-title'])  && !empty($_POST['item-price'])) {
    $item_title = test_input($_POST['item-title']);
    $item_price = test_input($_POST['item-price']);
    array_push($input_order_arr,$item_title,$item_price);

    $_SESSION['chosen_item'][] = $input_order_arr;
  }
}
</code>```

Body:
I'm building an interface for an online shop, where every item is a FORM and the BUY button is a submit,it submits the name and price of the clicked form and that data is displayed on a CONFIRM ORDER page. On that confirm order page I've created an array as follows

if (!isset($input_order_arr)) {
  $input_order_arr = array();
}

After that I fetch the posted variables and push them into the array

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
  if (!empty($_POST['item-title'])  && !empty($_POST['item-price'])) {
    $item_title = test_input($_POST['item-title']);
    $item_price = test_input($_POST['item-price']);
    array_push($input_order_arr,$item_title,$item_price);
  }
}

$_SESSION['chosen_item'] = $input_order_arr;

*NOTE : test_input is a function that does striplashes , htmlspecialchars and htmltrim, for security purposes. (someone might edit the value of the item via the Chrome developer console? not sure if that holds any threat though)

And after that the value is displayed in a table like so

              <?php if (isset($_SESSION['chosen_item'])) {
                foreach ($_SESSION['chosen_item'] as $value) {
                  echo "" . $value . "	";
                }
              }  ?>

And here comes the problem.

If you order an item its price and name are displayed, but if u go back and you order another item, the previous item and its price are lost, as if its not adding new lines to the array,but replacing the old ones, or the session only saves data from one action, which wouldn't make any sense, since thats what $_SESSION is about, the code is presented with session_start(); in every page that is using the $_SESSION variable.

 Main Question - Why could it be that the $_SESSION Array is losing its older inputs?

Body:
When you go back, you basically are setting the chosen_item array element to empty, since $input_order_arr would not contain anything when you haven't submitted a form.

You should append to the session array only if there is a nonempty $input_order_arr array:

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
  if (!empty($_POST['item-title'])  && !empty($_POST['item-price'])) {
    $item_title = test_input($_POST['item-title']);
    $item_price = test_input($_POST['item-price']);
    array_push($input_order_arr,$item_title,$item_price);

    $_SESSION['chosen_item'][] = $input_order_arr;
  }
}


问:
C# Update in ado.net
Old records are not deleting. Update acts like insert.</p>

```<code>cn.Open();

string gen;
if (radioButton1.Checked == true)
    gen = "Male";
else
    gen = "Female";
string clas = null;

clas = comboBox1.Text;

string section = null;
section = comboBox2.Text;
SqlCommand cmd = new SqlCommand("update studetail set name='" + textBox2.Text + "','" + gen + "','" + textBox3.Text + "','" + clas + "','" + section + "' where studentno='" + textBox1.Text + "'");
cmd.Connection = cn;

int n = cmd.ExecuteNonQuery();
</code>```

答:
update acts like insert.

That's obvious cause you made it like so. Your below UPDATE statement is syntactically wrong

```<code>update studetail set name='" + textBox2.Text + "','" + gen + "','" + textBox3.Text + "','" + clas + "','" + section
</code>```

It rather should be

```<code>update studetail set name='" + textBox2.Text + "',' gender = " + gen + "','" ...
</code>```

Finally, you should consider using parameterized queries instead of concatanating user input likewise you are doing. It's prone to SQL Injection

```<code>SqlCommand cmd = new SqlCommand("update studetail set name= @name, gender = @gender, clas = @clas, section = @section where studentno = @studentno");

cmd.Parameters.Add(new SqlParameter("name", textBox2.Text));
cmd.Parameters.Add(new SqlParameter("gender", gen));
cmd.Parameters.Add(new SqlParameter("clas", clas));
cmd.Parameters.Add(new SqlParameter("section", section));
cmd.Parameters.Add(new SqlParameter("studentno", textBox1.Text));
</code>```

Title: C# Update in ado.net

Body:
Old records are not deleting. Update acts like insert.

cn.Open();

string gen;
if (radioButton1.Checked == true)
    gen = "Male";
else
    gen = "Female";
string clas = null;

clas = comboBox1.Text;

string section = null;
section = comboBox2.Text;
SqlCommand cmd = new SqlCommand("update studetail set name='" + textBox2.Text + "','" + gen + "','" + textBox3.Text + "','" + clas + "','" + section + "' where studentno='" + textBox1.Text + "'");
cmd.Connection = cn;

int n = cmd.ExecuteNonQuery();

Body:
update acts like insert.

That's obvious cause you made it like so. Your below UPDATE statement is syntactically wrong

update studetail set name='" + textBox2.Text + "','" + gen + "','" + textBox3.Text + "','" + clas + "','" + section

It rather should be

update studetail set name='" + textBox2.Text + "',' gender = " + gen + "','" ...

Finally, you should consider using parameterized queries instead of concatanating user input likewise you are doing. It's prone to SQL Injection

SqlCommand cmd = new SqlCommand("update studetail set name= @name, gender = @gender, clas = @clas, section = @section where studentno = @studentno");

cmd.Parameters.Add(new SqlParameter("name", textBox2.Text));
cmd.Parameters.Add(new SqlParameter("gender", gen));
cmd.Parameters.Add(new SqlParameter("clas", clas));
cmd.Parameters.Add(new SqlParameter("section", section));
cmd.Parameters.Add(new SqlParameter("studentno", textBox1.Text));


问:
Why can not I append script to DOM on mobile browsers
Why can not I append script to DOM on mobile browsers. It looks like manipulating the dom is completely different in mobile browsers, but actually have no idea in what sense. I ve not got smth like that before, it was always ok. It also looks like the problem is not so actual, as I can not find a much proper info about it down here on stackoverflow. All suggestions to similar questions are mostly about syntax errors or even smth meaningless. In my code there are no mistakes, and this makes debugging really hard. Does anyone has an idea or maybe has encountered with smth like this?

```<code>function thumb_handler(data) {

    console.log(data);

    let icons = document.querySelectorAll('.messenger-wrap a span');

    for (var i = 0; i < icons.length; i++) {

        if (icons[i].getAttribute('class') == data.class) icons[i].style.background = 'url(' + data.img + ')';

    }

}

function requestServerCall(cls, img) {
    var head = document.head;
    var script = document.createElement('script');
    script.type  = "text/javascript";
    script.text  = "alert('voila!');"

    script.setAttribute('src', 'http://inmrkt/general.php?do=load_icons&callback=thumb_handler&class=' + cls + '&img=' + img);
    head.appendChild(script);
    // head.removeChild(script);
}

function icon_loader() {

    let icons = document.querySelectorAll('.messenger-wrap a span');

    for (var i = 0; i < icons.length; i++) {

        let img = icons[i].getAttribute('data-img'),
            cls = icons[i].getAttribute('class');

        requestServerCall(cls, img);

    }

}

icon_loader();
</code>```

It is completely ok on any desktop, but not on mobiles. It just does not appear in the dom tree.

enter image description here

答:
The issue was that I was trying to make the code work on a server without checking twice if any stuff for local environment is still present.

```<code>script.setAttribute('src', 'http://inmrkt/general.php?do=load_icons&callback=thumb_handler&class=' + cls + '&img=' + img);
</code>```

url obviously points to a localhost domain... And should be as following:

```<code>script.setAttribute('src', 'http://example.com/general.php?do=load_icons&callback=thumb_handler&class=' + cls + '&img=' + img);
</code>```

or

```<code>script.setAttribute('src', 'general.php?do=load_icons&callback=thumb_handler&class=' + cls + '&img=' + img);
</code>```

Body:
Why can not I append script to DOM on mobile browsers. It looks like manipulating the dom is completely different in mobile browsers, but actually have no idea in what sense. I ve not got smth like that before, it was always ok. It also looks like the problem is not so actual, as I can not find a much proper info about it down here on stackoverflow. All suggestions to similar questions are mostly about syntax errors or even smth meaningless. In my code there are no mistakes, and this makes debugging really hard. Does anyone has an idea or maybe has encountered with smth like this?

function thumb_handler(data) {

    console.log(data);

    let icons = document.querySelectorAll('.messenger-wrap a span');

    for (var i = 0; i < icons.length; i++) {

        if (icons[i].getAttribute('class') == data.class) icons[i].style.background = 'url(' + data.img + ')';

    }

}

function requestServerCall(cls, img) {
    var head = document.head;
    var script = document.createElement('script');
    script.type  = "text/javascript";
    script.text  = "alert('voila!');"

    script.setAttribute('src', 'http://inmrkt/general.php?do=load_icons&callback=thumb_handler&class=' + cls + '&img=' + img);
    head.appendChild(script);
    // head.removeChild(script);
}

function icon_loader() {

    let icons = document.querySelectorAll('.messenger-wrap a span');

    for (var i = 0; i < icons.length; i++) {

        let img = icons[i].getAttribute('data-img'),
            cls = icons[i].getAttribute('class');

        requestServerCall(cls, img);

    }

}

icon_loader();

It is completely ok on any desktop, but not on mobiles. It just does not appear in the dom tree.

enter image description here

Body:
The issue was that I was trying to make the code work on a server without checking twice if any stuff for local environment is still present.

script.setAttribute('src', 'http://inmrkt/general.php?do=load_icons&callback=thumb_handler&class=' + cls + '&img=' + img);

url obviously points to a localhost domain... And should be as following:

script.setAttribute('src', 'http://example.com/general.php?do=load_icons&callback=thumb_handler&class=' + cls + '&img=' + img);

or

script.setAttribute('src', 'general.php?do=load_icons&callback=thumb_handler&class=' + cls + '&img=' + img);


问:
Vue.js - Don't bind an object when 'copying it' to another data attribute
I have an object coming from my API and when loading a modal I need to 'duplicate' the object to another.

This works:

```<code>this.servicesForm.services = this.team.services;

// New object                // API object
</code>```

The issue now is that I DON'T want the team.services object to be bound to and update when I update the servicesForm.services object.

How do I do that?

答:
Quickly found my answer:</p>

```<code>this.servicesForm.services = JSON.parse(JSON.stringify(this.team.services));
</code>```

Body:
I have an object coming from my API and when loading a modal I need to 'duplicate' the object to another.

This works:

this.servicesForm.services = this.team.services;

// New object                // API object

The issue now is that I DON'T want the team.services object to be bound to and update when I update the servicesForm.services object.

How do I do that?

Body:
Quickly found my answer:

this.servicesForm.services = JSON.parse(JSON.stringify(this.team.services));


问:
Fixed sidebar with one overflowing content and one fixed content
I'm working on a simple layout, but one thing is bugging me.
I want a layout with two columns, full height, a sidebar and the content.
Inside the sidebar, I want two things:

One button that will be positioned at the bottom, fixed height.

One div that will be centered in the remaining space, fluid height.

I try to be IE 9 compatible.

This is the basic layout:

```<code><aside>
  <div class="wrapper">
    <nav>
      <ul>
        <li>Item menu</li>
        <li>Item menu</li>
        <li>Item menu n</li>
      </ul>
    </nav>
  </div>
  <a class="btn">
    button must be at the bottom
  </a>
</aside>
<main>
  My content
</main>
</code>```

And the basic css:

```<code>* { margin:0; padding: 0; box-sizing:border-box; }
html, body { height: 100%; }
aside, main { height: 100%; }
aside {
  position:fixed;
  left:0;
  top:0;
  width: 200px;
  background:#eee;
}
main {
  width: calc(100% - 200px);
  margin-left:200px;
}
</code>```

For now, anything I try result in having problem when the window height is small. (The button over the menu, or no scrollbar for the menu, etc...)

What I've tryed:

aside{display:table}, .wrapper{display:tablle-cell; vertical-align:middle} with .btn{position: fixed; bottom:0; left:0;}

nav{top:50%; transform:translateY(-50%);} but then, there is a point where the content of the nav will go on top of the viewport...

and a bit of flexbox, but I could'nt achieve the wanted result.

If you need more information, I would be more than welcome to give them.
Thank you.

答:
This should help you get started.

UPDATED

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  display: flex;
  height: 100vh;
  overflow: hidden;
}

aside,
main {
  /*   height: 100%; */
  /*   width: 100%; */
}

aside {
  flex-grow: 1;
  background: #eee;
  padding: 5px;
}

main {
  flex-grow: 6;
  background: #ddd;
  padding: 20px;
  height: 100vh;
  overflow-y: scroll;
}

.wrapper {
  display: flex;
  height: 100vh;
  justify-content: space-between;
  flex-direction: column;
}

.btn {
  margin: 20px auto;
  background: #bada55;
  padding: 20px;
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><aside>
  <div class="wrapper">
    <nav>
      <ul>
        <li>Item menu</li>
        <li>Item menu</li>
        <li>Item menu n</li>
      </ul>
    </nav>

button

  </div>

</aside>
<main>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloremque ex, obcaecati eveniet distinctio provident tempora, voluptatum, quisquam dicta autem blanditiis quae consectetur cupiditate aliquam architecto quia, labore dolores qui unde.Lorem ipsum
    dolor sit amet, consectetur adipisicing elit. Doloremque ex, obcaecati eveniet distinctio provident tempora, voluptatum, quisquam dicta autem blanditiis quae consectetur cupiditate aliquam architecto quia, labore dolores qui unde.Lorem ipsum dolor
    sit amet, consectetur adipisicing elit. Doloremque ex, obcaecati eveniet distinctio provident tempora, voluptatum, quisquam dicta autem blanditiis quae consectetur cupiditate aliquam architecto quia, labore dolores qui unde.Lorem ipsum dolor sit amet,
    consectetur adipisicing elit. Doloremque ex, obcaecati eveniet distinctio provident tempora, voluptatum, quisquam dicta autem blanditiis quae consectetur cupiditate aliquam architecto quia, labore dolores qui unde.Lorem ipsum dolor sit amet, consectetur
    adipisicing elit. Doloremque ex, obcaecati eveniet distinctio provident tempora, voluptatum, quisquam dicta autem blanditiis quae consectetur cupiditate aliquam architecto quia, labore dolores qui unde.Lorem ipsum dolor sit amet, consectetur adipisicing
    elit. Doloremque ex, obcaecati eveniet distinctio provident tempora, voluptatum, quisquam dicta autem blanditiis quae consectetur cupiditate aliquam architecto quia, labore dolores qui unde.Lorem ipsum dolor sit amet, consectetur adipisicing elit.
    Doloremque ex, obcaecati eveniet distinctio provident tempora, voluptatum, quisquam dicta autem blanditiis quae consectetur cupiditate aliquam architecto quia, labore dolores qui unde.Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloremque
    ex, obcaecati eveniet distinctio provident tempora, voluptatum, quisquam dicta autem blanditiis quae consectetur cupiditate aliquam architecto quia, labore dolores qui unde.Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloremque ex, obcaecati
    eveniet distinctio provident tempora, voluptatum, quisquam dicta autem blanditiis quae consectetur cupiditate aliquam architecto quia, labore dolores qui unde.Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloremque ex, obcaecati eveniet
    distinctio provident tempora, voluptatum, quisquam dicta autem blanditiis quae consectetur cupiditate aliquam architecto quia, labore dolores qui unde.Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloremque ex, obcaecati eveniet distinctio
    provident tempora, voluptatum, quisquam dicta autem blanditiis quae consectetur cupiditate aliquam architecto quia, labore dolores qui unde.</p>
</main></code>```

Body:
I'm working on a simple layout, but one thing is bugging me.
I want a layout with two columns, full height, a sidebar and the content.
Inside the sidebar, I want two things:

One button that will be positioned at the bottom, fixed height.

One div that will be centered in the remaining space, fluid height.

I try to be IE 9 compatible.

This is the basic layout:

Item menu

Item menu

Item menu n

    button must be at the bottom

  My content

And the basic css:

* { margin:0; padding: 0; box-sizing:border-box; }
html, body { height: 100%; }
aside, main { height: 100%; }
aside {
  position:fixed;
  left:0;
  top:0;
  width: 200px;
  background:#eee;
}
main {
  width: calc(100% - 200px);
  margin-left:200px;
}

For now, anything I try result in having problem when the window height is small. (The button over the menu, or no scrollbar for the menu, etc...)

What I've tryed:

aside{display:table}, .wrapper{display:tablle-cell; vertical-align:middle} with .btn{position: fixed; bottom:0; left:0;}

nav{top:50%; transform:translateY(-50%);} but then, there is a point where the content of the nav will go on top of the viewport...

and a bit of flexbox, but I could'nt achieve the wanted result.

If you need more information, I would be more than welcome to give them.
Thank you.

Body:
This should help you get started.

UPDATED

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  display: flex;
  height: 100vh;
  overflow: hidden;
}

aside,
main {
  /*   height: 100%; */
  /*   width: 100%; */
}

aside {
  flex-grow: 1;
  background: #eee;
  padding: 5px;
}

main {
  flex-grow: 6;
  background: #ddd;
  padding: 20px;
  height: 100vh;
  overflow-y: scroll;
}

.wrapper {
  display: flex;
  height: 100vh;
  justify-content: space-between;
  flex-direction: column;
}

.btn {
  margin: 20px auto;
  background: #bada55;
  padding: 20px;
}

<aside>
  <div class="wrapper">
    <nav>
      <ul>
        <li>Item menu</li>
        <li>Item menu</li>
        <li>Item menu n</li>
      </ul>
    </nav>
    <a class="btn">
button
  </a>
  </div>

</aside>
<main>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloremque ex, obcaecati eveniet distinctio provident tempora, voluptatum, quisquam dicta autem blanditiis quae consectetur cupiditate aliquam architecto quia, labore dolores qui unde.Lorem ipsum
    dolor sit amet, consectetur adipisicing elit. Doloremque ex, obcaecati eveniet distinctio provident tempora, voluptatum, quisquam dicta autem blanditiis quae consectetur cupiditate aliquam architecto quia, labore dolores qui unde.Lorem ipsum dolor
    sit amet, consectetur adipisicing elit. Doloremque ex, obcaecati eveniet distinctio provident tempora, voluptatum, quisquam dicta autem blanditiis quae consectetur cupiditate aliquam architecto quia, labore dolores qui unde.Lorem ipsum dolor sit amet,
    consectetur adipisicing elit. Doloremque ex, obcaecati eveniet distinctio provident tempora, voluptatum, quisquam dicta autem blanditiis quae consectetur cupiditate aliquam architecto quia, labore dolores qui unde.Lorem ipsum dolor sit amet, consectetur
    adipisicing elit. Doloremque ex, obcaecati eveniet distinctio provident tempora, voluptatum, quisquam dicta autem blanditiis quae consectetur cupiditate aliquam architecto quia, labore dolores qui unde.Lorem ipsum dolor sit amet, consectetur adipisicing
    elit. Doloremque ex, obcaecati eveniet distinctio provident tempora, voluptatum, quisquam dicta autem blanditiis quae consectetur cupiditate aliquam architecto quia, labore dolores qui unde.Lorem ipsum dolor sit amet, consectetur adipisicing elit.
    Doloremque ex, obcaecati eveniet distinctio provident tempora, voluptatum, quisquam dicta autem blanditiis quae consectetur cupiditate aliquam architecto quia, labore dolores qui unde.Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloremque
    ex, obcaecati eveniet distinctio provident tempora, voluptatum, quisquam dicta autem blanditiis quae consectetur cupiditate aliquam architecto quia, labore dolores qui unde.Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloremque ex, obcaecati
    eveniet distinctio provident tempora, voluptatum, quisquam dicta autem blanditiis quae consectetur cupiditate aliquam architecto quia, labore dolores qui unde.Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloremque ex, obcaecati eveniet
    distinctio provident tempora, voluptatum, quisquam dicta autem blanditiis quae consectetur cupiditate aliquam architecto quia, labore dolores qui unde.Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloremque ex, obcaecati eveniet distinctio
    provident tempora, voluptatum, quisquam dicta autem blanditiis quae consectetur cupiditate aliquam architecto quia, labore dolores qui unde.</p>
</main>


问:
Laravel get product id from collection
I want to get all the products by passing array of ids which are from other table

i'm able to get all the product_id as in the dd($main_categorie_ids); but unable to pass it in other query and get the required data

```<code>    public function getHomeData($warehouse_id)
    {
        //get warehouse_table_name by warehouse_id
        $warehouse_table = Warehouse::where('id', $warehouse_id)
                                    ->select('table_name')
                                    ->first();

        //get all products from warehouse_table_name table
        $main_categorie_ids = DB::table($warehouse_table->table_name)
                                ->select('product_id')
                                ->get()
                                ->toArray();

        dd($main_categorie_ids);

        //dd result
        array:2 [
          0 => {#210
            +"product_id": 1
          }
          1 => {#209
            +"product_id": 2
          }
        ]

        //get distinct main_categories by id (line 29)
        $main_categorie = Product::whereIn('id', $main_categorie_ids['product_id'])
                                 ->groupBy('main_category_id')
                                 ->get();

        //get banners of main_categories by id

        //get parent_categories by main_category_id
    }
</code>```

i am getting error

```<code>(1/1) ErrorException
Undefined index: product_id
in HomeController.php (line 29)
</code>```

thank you

答:
you are having more than 1 array in the collection so to use a specific one you need to pass the index
so try this

```<code>$main_categorie = Product::whereIn('id', $main_categorie_ids[0]->product_id)->get();
</code>```

for the 1st one, if you want to access the 2nd one

```<code>$main_categorie = Product::whereIn('id', $main_categorie_ids[1]->product_id)->get();
</code>```

Title: Laravel get product id from collection

Body:
I want to get all the products by passing array of ids which are from other table

i'm able to get all the product_id as in the dd($main_categorie_ids); but unable to pass it in other query and get the required data

    public function getHomeData($warehouse_id)
    {
        //get warehouse_table_name by warehouse_id
        $warehouse_table = Warehouse::where('id', $warehouse_id)
                                    ->select('table_name')
                                    ->first();

        //get all products from warehouse_table_name table
        $main_categorie_ids = DB::table($warehouse_table->table_name)
                                ->select('product_id')
                                ->get()
                                ->toArray();

        dd($main_categorie_ids);

        //dd result
        array:2 [
          0 => {#210
            +"product_id": 1
          }
          1 => {#209
            +"product_id": 2
          }
        ]

        //get distinct main_categories by id (line 29)
        $main_categorie = Product::whereIn('id', $main_categorie_ids['product_id'])
                                 ->groupBy('main_category_id')
                                 ->get();

        //get banners of main_categories by id

        //get parent_categories by main_category_id
    }

i am getting error

(1/1) ErrorException
Undefined index: product_id
in HomeController.php (line 29)

thank you

Body:
you are having more than 1 array in the collection so to use a specific one you need to pass the index
so try this

$main_categorie = Product::whereIn('id', $main_categorie_ids[0]->product_id)->get();

for the 1st one, if you want to access the 2nd one

$main_categorie = Product::whereIn('id', $main_categorie_ids[1]->product_id)->get();


问:
How to return a nil CGFloat?
I'd like to return nil to tableView:heightForFooterInSection: but that's not allowed.  Is there a way to return nil as a CGFloat?

Why are you doing this?

I'm testing how a tableView will behave with a mix of Titles and Views as sectionFooters. For one footer I need to use a custom view, but for another footer I have 3 or 4 sentences of text and I like how the system styles it and sizes the footer to fit.  But as soon as I implement heightForFooterInSection (which is required by viewForFooterInSection), the footer with the title no longer auto-resizes to fit the given text. I'm trying to avoid building a custom view for the straight text.

答:
I am late for the party but this may be useful to someone.

Like others said, you cannot return nil to primitives but you can do one of two things, to differentiate a non-set value from a set one.

Use NSNotFound

```<code>- (CGFloat)calculateHeight {
   // calculate height...

   if (heightInvalid) return NSNotFound;
   else return validFloatValue;

}
</code>```

NSNotFound is a huge number defined by Apple and used by them on some operations. Then you can check for that, like:

```<code>if ([self calculateHeight] == NSNotFound) ...
</code>```

Use NSNumber

Instead of returning a CGFloat make your function return a NSNumber.

```<code>      - (NSNumber *)calculateHeight {
         // calculate height...

         if (heightInvalid) return nil;
         else return @(validFloatValue);

      }
</code>```

Then, you can return nil.

When receiving the value you do:

```<code>NSNumber *myHeightNumber = [self calculateHeight];
if (!myHeightNumber) NSLog(@"height is invalid... do something");
else myHeight = [myHeightNumber floatValue];
</code>```

I hope that helps.

Title: How to return a nil CGFloat?

Body:
I am late for the party but this may be useful to someone.

Like others said, you cannot return nil to primitives but you can do one of two things, to differentiate a non-set value from a set one.

Use NSNotFound

- (CGFloat)calculateHeight {
   // calculate height...

   if (heightInvalid) return NSNotFound;
   else return validFloatValue;

}

NSNotFound is a huge number defined by Apple and used by them on some operations. Then you can check for that, like:

if ([self calculateHeight] == NSNotFound) ...

Use NSNumber

Instead of returning a CGFloat make your function return a NSNumber.

      - (NSNumber *)calculateHeight {
         // calculate height...

         if (heightInvalid) return nil;
         else return @(validFloatValue);

      }

Then, you can return nil.

When receiving the value you do:

NSNumber *myHeightNumber = [self calculateHeight];
if (!myHeightNumber) NSLog(@"height is invalid... do something");
else myHeight = [myHeightNumber floatValue];

I hope that helps.


问:
Establish callback in Swift for PubNub 4.0 to receive messages
It appears to me that the documentation PubNub has for getting started in Swift don't apply to versions earlier than PubNub 4.0.  I can't successfully establish a callback to register with PubNub.

My code:

```<code>class Communicator: NSObject, PNObjectEventListener {

    var pubNubClient: PubNub

    override init(){
        let config = PNConfiguration(
            publishKey: "my_publish_key",
            subscribeKey: "my_subscribe_key"
        )
        pubNubClient = PubNub.clientWithConfiguration(config);
        super.init()
        pubNubClient.addListener(self)
        pubNubClient.subscribeToChannels(["my_channel"], withPresence: false)
    }

    func didReceiveMessage(client: PubNub!, message: PNMessageResult!){
        /* THIS METHOD NEVER GETS REACHED */
    }
}
</code>```

Digging into the PubNub source a bit, this is the area that seems to be having problems:

```<code>- (void)addListener:(id <PNObjectEventListener>)listener {

    dispatch_async(self.resourceAccessQueue, ^{

        if ([listener respondsToSelector:@selector(client:didReceiveMessage:)]) {
            /* this block is never reached!!! */
            [self.messageListeners addObject:listener];
        }

    /* Remaining Lines Stripped Away */
    });
}
</code>```

I'm still relatively new to Swift and integrating with Objective C.  I'm curious if there's a problem with the respondsToSelector since the Objective C code is referencing Swift code.

The messages are definitely getting passed; there's another lower level function in the PubNub library that's logging all the messages received.

Any help would be much appreciated.

答:
add _ client works for me!

```<code>func client(_ client: PubNub, didReceiveMessage message: PNMessageResult) {
    print("Pubnub Message: \(message)")
}
</code>```

Body:
It appears to me that the documentation PubNub has for getting started in Swift don't apply to versions earlier than PubNub 4.0.  I can't successfully establish a callback to register with PubNub.

My code:

class Communicator: NSObject, PNObjectEventListener {

    var pubNubClient: PubNub

    override init(){
        let config = PNConfiguration(
            publishKey: "my_publish_key",
            subscribeKey: "my_subscribe_key"
        )
        pubNubClient = PubNub.clientWithConfiguration(config);
        super.init()
        pubNubClient.addListener(self)
        pubNubClient.subscribeToChannels(["my_channel"], withPresence: false)
    }

    func didReceiveMessage(client: PubNub!, message: PNMessageResult!){
        /* THIS METHOD NEVER GETS REACHED */
    }
}

Digging into the PubNub source a bit, this is the area that seems to be having problems:

- (void)addListener:(id <PNObjectEventListener>)listener {

    dispatch_async(self.resourceAccessQueue, ^{

        if ([listener respondsToSelector:@selector(client:didReceiveMessage:)]) {
            /* this block is never reached!!! */
            [self.messageListeners addObject:listener];
        }

    /* Remaining Lines Stripped Away */
    });
}

I'm still relatively new to Swift and integrating with Objective C.  I'm curious if there's a problem with the respondsToSelector since the Objective C code is referencing Swift code.

The messages are definitely getting passed; there's another lower level function in the PubNub library that's logging all the messages received.

Any help would be much appreciated.

Body:
add _ client works for me!

func client(_ client: PubNub, didReceiveMessage message: PNMessageResult) {
    print("Pubnub Message: \(message)")
}


问:
Getting deployment error when deploying sample script in Developer composer playground
I'm trying to setup the development environment for composer by following the steps in the tutorial. I was able to generate the .bna file successfully and use it in the online playground. But when I try to deploy the .bna file to the fabric V1.0 running in my local, I get the below error.

```<code>ubuntu@ip-172-31-8-83:~/fabric-tools/my-network$ cd dist
ubuntu@ip-172-31-8-83:~/fabric-tools/my-network/dist$ composer network
deploy -a my-network.bna -p hlfv1 -i PeerAdmin -s randomString

Deploying business network from archive: my-network.bna
Business network definition:
    Identifier: my-network@0.0.1
    Description: The Hello World of Hyperledger Composer samples

events.js:160
  throw er; // Unhandled 'error' event
  ^

Error: event message must be properly signed by an identity from the same organization as the peer: [failed deserializing event creator: [Expected MSP ID Org1MSP, received ]]
at ClientDuplexStream._emitStatusIfDone (/home/ubuntu/.nvm/versions/node/v6.11.0/lib/node_modules/composer-cli/node_modules/grpc/src/node/src/client.js:189:19)
at ClientDuplexStream._receiveStatus (/home/ubuntu/.nvm/versions/node/v6.11.0/lib/node_modules/composer-cli/node_modules/grpc/src/node/src/client.js:169:8)
at /home/ubuntu/.nvm/versions/node/v6.11.0/lib/node_modules/composer-cli/node_modules/grpc/src/node/src/client.js:634:14
</code>```

My docker images are as follows:

```<code>ubuntu@ip-172-31-8-83:~/fabric-tools/my-network/dist$ docker ps -a
CONTAINER ID        IMAGE                                          COMMAND
CREATED             STATUS              PORTS
NAMES
80c9949edf73        hyperledger/fabric-peer:x86_64-1.0.0-beta      "peer
node start -..."   19 minutes ago      Up 19 minutes       0.0.0.0:7051-
>7051/tcp, 0.0.0.0:7053->7053/tcp   peer0.org1.example.com
126f6381cc90        hyperledger/fabric-couchdb:x86_64-1.0.0-beta   "tini --
/docker-e..."   19 minutes ago      Up 19 minutes       4369/tcp, 9100/tcp,
0.0.0.0:5984->5984/tcp       couchdb
924081546fa1        hyperledger/fabric-ca:x86_64-1.0.0-beta        "sh -c
'fabric-ca-..."   19 minutes ago      Up 19 minutes       0.0.0.0:7054-
>7054/tcp                           ca.example.com
d13f2c8e8421        hyperledger/fabric-orderer:x86_64-1.0.0-beta   "orderer"
19 minutes ago      Up 19 minutes       0.0.0.0:7050->7050/tcp
orderer.example.com
</code>```

Node version is: 4.2.6
npm version is : 3.5.2
Docker version 17.06.0-ce, build 02c1d87

Can someone tell me how to resolve this?

答:
you need to be at the latest Node level - you're currently at 4.2.6 - you need to be at node version 6.x
https://hyperledger.github.io/composer/unstable/installing/development-tools.html

I assume you're using Ubuntu 14.04 or 16.0x LTS ..

Body:
I'm trying to setup the development environment for composer by following the steps in the tutorial. I was able to generate the .bna file successfully and use it in the online playground. But when I try to deploy the .bna file to the fabric V1.0 running in my local, I get the below error.

ubuntu@ip-172-31-8-83:~/fabric-tools/my-network$ cd dist
ubuntu@ip-172-31-8-83:~/fabric-tools/my-network/dist$ composer network
deploy -a my-network.bna -p hlfv1 -i PeerAdmin -s randomString

Deploying business network from archive: my-network.bna
Business network definition:
    Identifier: my-network@0.0.1
    Description: The Hello World of Hyperledger Composer samples

events.js:160
  throw er; // Unhandled 'error' event
  ^

Error: event message must be properly signed by an identity from the same organization as the peer: [failed deserializing event creator: [Expected MSP ID Org1MSP, received ]]
at ClientDuplexStream._emitStatusIfDone (/home/ubuntu/.nvm/versions/node/v6.11.0/lib/node_modules/composer-cli/node_modules/grpc/src/node/src/client.js:189:19)
at ClientDuplexStream._receiveStatus (/home/ubuntu/.nvm/versions/node/v6.11.0/lib/node_modules/composer-cli/node_modules/grpc/src/node/src/client.js:169:8)
at /home/ubuntu/.nvm/versions/node/v6.11.0/lib/node_modules/composer-cli/node_modules/grpc/src/node/src/client.js:634:14

My docker images are as follows:

ubuntu@ip-172-31-8-83:~/fabric-tools/my-network/dist$ docker ps -a
CONTAINER ID        IMAGE                                          COMMAND
CREATED             STATUS              PORTS
NAMES
80c9949edf73        hyperledger/fabric-peer:x86_64-1.0.0-beta      "peer
node start -..."   19 minutes ago      Up 19 minutes       0.0.0.0:7051-
>7051/tcp, 0.0.0.0:7053->7053/tcp   peer0.org1.example.com
126f6381cc90        hyperledger/fabric-couchdb:x86_64-1.0.0-beta   "tini --
/docker-e..."   19 minutes ago      Up 19 minutes       4369/tcp, 9100/tcp,
0.0.0.0:5984->5984/tcp       couchdb
924081546fa1        hyperledger/fabric-ca:x86_64-1.0.0-beta        "sh -c
'fabric-ca-..."   19 minutes ago      Up 19 minutes       0.0.0.0:7054-
>7054/tcp                           ca.example.com
d13f2c8e8421        hyperledger/fabric-orderer:x86_64-1.0.0-beta   "orderer"
19 minutes ago      Up 19 minutes       0.0.0.0:7050->7050/tcp
orderer.example.com

Node version is: 4.2.6
npm version is : 3.5.2
Docker version 17.06.0-ce, build 02c1d87

Can someone tell me how to resolve this?


问:
My multilanguage menu for wordpress site
I have a word press site and i need to add multi language. I've add the WPML plugin but i don't like how the menu for language is shown. I added manually in header.php in a div the two languages (En, It).
Is there anyway to add script so these two "buttons" to be my multilanguage menu?

Thanx in adv.

答:
WPML is quite good at adding in the switcher automatically. To do this you will need to go through the settings option in WPML to tell it how and where to display the switcher. You should complete these settings anyway inorder to make sute WPML is able to function properly.

However, you can add it manually, with the following code. Keep in mind that you will probably need to manually change the menu name to match that of your theme.

```<code>// Filter wp_nav_menu() to add additional links and other output
// Show only other language in language switcher
// Use the new filter: https://wpml.org/wpml-hook/wpml_active_languages/
add_filter('wp_nav_menu_items', 'new_nav_menu_items', 10, 2);
function new_nav_menu_items($items, $args) {
    // uncomment this to find your theme's menu location
    //echo "args:
```"; print_r($args); echo "```

";

    // get languages
    $languages = apply_filters( 'wpml_active_languages', NULL, 'skip_missing=0' );

    // add $args->theme_location == 'primary-menu' in the conditional if we want to specify the menu location.

    if ( $languages && $args->theme_location == 'primary') {

        if(!empty($languages)){

            foreach($languages as $l){
                if(!$l['active']){
                    // flag with native name
                    $items = $items . '
<li class="menu-item"><img src="' . $l['country_flag_url'] . '" height="12" alt="' . $l['language_code'] . '" width="18" /> ' . $l['native_name'] . '</li>

';
                    //only flag
                    //$items = $items . '
<li class="menu-item menu-item-language"><img src="' . $l['country_flag_url'] . '" height="12" alt="' . $l['language_code'] . '" width="18" /></li>

';
                }
            }
        }
    }

    return $items;
}
</code>```

Body:
WPML is quite good at adding in the switcher automatically. To do this you will need to go through the settings option in WPML to tell it how and where to display the switcher. You should complete these settings anyway inorder to make sute WPML is able to function properly.

However, you can add it manually, with the following code. Keep in mind that you will probably need to manually change the menu name to match that of your theme.

// Filter wp_nav_menu() to add additional links and other output
// Show only other language in language switcher
// Use the new filter: https://wpml.org/wpml-hook/wpml_active_languages/
add_filter('wp_nav_menu_items', 'new_nav_menu_items', 10, 2);
function new_nav_menu_items($items, $args) {
    // uncomment this to find your theme's menu location
    //echo "args:
<pre>"; print_r($args); echo "</pre>

";

    // get languages
    $languages = apply_filters( 'wpml_active_languages', NULL, 'skip_missing=0' );

    // add $args->theme_location == 'primary-menu' in the conditional if we want to specify the menu location.

    if ( $languages && $args->theme_location == 'primary') {

        if(!empty($languages)){

            foreach($languages as $l){
                if(!$l['active']){
                    // flag with native name
                    $items = $items . '
<li class="menu-item"><a href="' . $l['url'] . '"><img src="' . $l['country_flag_url'] . '" height="12" alt="' . $l['language_code'] . '" width="18" /> ' . $l['native_name'] . '</a></li>

';
                    //only flag
                    //$items = $items . '
<li class="menu-item menu-item-language"><a href="' . $l['url'] . '"><img src="' . $l['country_flag_url'] . '" height="12" alt="' . $l['language_code'] . '" width="18" /></a></li>

';
                }
            }
        }
    }

    return $items;
}