簡體   English   中英

可靠的服務發現問題

[英]issue with reliable service discovery

我把頭撞在牆上。 它有效,但是不起作用。

讓我澄清一下,測試是在所有運行4.1+的LG Optimus G,Galaxy S4和Lenovo Tablet上進行的

我正在每個設備上啟動服務器,每個設備都在端口上廣播自己,當用戶點擊send時,所有已解決其服務且未丟失服務的設備,一個線程將循環啟動其他線程以連接到廣播自己的服務器,然后發送數據。 服務器接受傳入的連接,將其交給線程,然后重新打開自己。

因此,回顧一下,每台設備都在廣播服務器,每台設備都應該知道並跟蹤其他服務器,在發送數據時,所有已知服務器都會受到攻擊。

我的問題是,在2/3設備中可以與設備自身建立一致的連接。

這兩個電話中的任何一個似乎一次都知道另一部電話,但能夠同時連接到另一部電話,但一次只能使用其中一部。 也就是說,Galaxy S4可以對Optimus G表示打招呼,但是Optimus G只能對自己打招呼,反之亦然。

因此,發現部分似乎不可靠,並且我不知道它是我,Android還是設備。 我需要外面的眼睛。 我試圖以一種可以理解和深思熟慮的方式進行布局,並且我很感謝任何對此問題有知識的人的幫助,因為我只是對網絡世界起一個卑微的開端,並且更願意從中學習某人。

我需要一種更可靠的方式來跟蹤服務或發現它們,因為我的實現至少看起來有缺陷。

感謝高級的任何幫助。 (我不認為這是一個像其他大多數Android區域一樣被嚴重踐踏的區域。)

在這里完成初始化。

/**initilize everything*/
private void buildNetwork()
{
    Log.d(TAG, "buildNetwork");
    networkHelper = new NetworkServiceDiscoveryHelper(this);
    networkHelper.initializeNsd(this);
    networkHelper.discoverServices();
    connectionReceiver = new ConnectionReceiver(this, this);
    // this next line launches the server thread which will obtain a socket
    // to be used in the finishBuildingNetwork()
    new Thread(connectionReceiver).start();

}

/** after the serversocket has been given a port we need to broadcast it*/
private void finishBuildingNetwork(int port)
{
    Log.d(TAG, "finishBuildingNetwork");
    networkHelper.registerService(port);
}

這是我對通用NSDManager幫助器類進行的更改。

public class NetworkServiceDiscoveryHelper
{

    public static final String TAG = "NetworkServiceDiscoveryHelper";
    public static final String KEY_DEVICE = "device";

    Context mContext;

    NsdManager mNsdManager;
    NsdManager.ResolveListener mResolveListener;
    NsdManager.DiscoveryListener mDiscoveryListener;
    NsdManager.RegistrationListener mRegistrationListener;

    public static final String SERVICE_TYPE = "_http._tcp.";

    public String mServiceName = "BlurbChat";

    NsdServiceInfo mService;

    private DiscoveredDevicesManager deviceManager;
    private NetworkDiscoveryHelperListener helperListener;

    /**
     * 
     * @param context
     *            - the activity context the service is to be attached to
     */
    public NetworkServiceDiscoveryHelper(Context context)
    {
        mContext = context;
        mNsdManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE);
        deviceManager = new DiscoveredDevicesManager();
    }

    /**
     * initialize the NetworkServiceDiscovery
     */
    public void initializeNsd(NetworkDiscoveryHelperListener helperListener)
    {
        this.helperListener = helperListener;

        initializeResolveListener();
        initializeDiscoveryListener();
        initializeRegistrationListener();

        // mNsdManager.init(mContext.getMainLooper(), this);

    }

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

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

            @Override
            public void onServiceFound(NsdServiceInfo service)
            {
                // A service was found! Do something with it.
                Log.d(TAG, "Service discovery success" + service);
                if (!service.getServiceType().equals(SERVICE_TYPE))
                {
                    // Service type is the string containing the protocol and
                    // transport layer for this service.
                    Log.d(TAG, "Unknown Service Type: " + service.getServiceType());
                }
                else if (service.getServiceName().contains(mServiceName))
                {
                    // we have found our service! we use .contains because if
                    // there are multiple device with the same service being
                    // broadcast they will appear with name + (index)
                    // Resolve a discovered service. An application can resolve
                    // a service right before establishing a connection to fetch
                    // the IP and port details on which to setup the connection.
                    Log.d(TAG, "Found My Service Type: " + service.getServiceType() + service.getServiceName());
                    helperListener.SERVICE_FOUND(service);
                    mNsdManager.resolveService(service, mResolveListener);
                }

                /***************************************************************
                 * Checking the service name isn't always necessary, and is only relevant if you want to connect to a specific application.
                 * For instance, the application might only want to connect to instances of itself running on other devices. However, if the
                 * application wants to connect to a network printer, it's enough to see that the service type is "_ipp._tcp".
                 ******************************************************/
            }

            /**
             * when we lose our service
             */
            @Override
            public void onServiceLost(NsdServiceInfo service)
            {
                // When the network service is no longer available.
                Log.e(TAG, "service lost" + service);

                // remove the service
                if (deviceManager.removeDevice(service) != null)
                {
                    helperListener.SERVIVCE_LOST(service);
                }
            }

            /**
             * when our service is stopped
             */
            @Override
            public void onDiscoveryStopped(String serviceType)
            {
                Log.i(TAG, "Discovery stopped: " + serviceType);
                helperListener.DISCOVERY_STOPPED(serviceType);
            }

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

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

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

            @Override
            public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode)
            {
                // Called when the resolve fails. Use the error code to debug.
                Log.e(TAG, "Resolve failed" + errorCode);
                helperListener.RESOLVE_FAILED(serviceInfo, errorCode);
            }

            @Override
            public void onServiceResolved(NsdServiceInfo serviceInfo)
            {
                Log.e(TAG, "Resolve Succeeded. " + serviceInfo);

                if (serviceInfo.getServiceName().equals(mServiceName))
                {
                    Log.d(TAG, "Same IP.");
                    return;
                }

                mService = serviceInfo;
                DiscoveredDevice device = new DiscoveredDevice(mService.getPort(), mService.getHost(), mService.getServiceName(), mService.getServiceType());
                deviceManager.addDevice(device);
                helperListener.RESOLVE_SUCCESS(serviceInfo);
            }
        };
    }

    private void initializeRegistrationListener()
    {
        mRegistrationListener = new NsdManager.RegistrationListener()
        {

            @Override
            public void onServiceRegistered(NsdServiceInfo serviceInfo)
            {
                mServiceName = serviceInfo.getServiceName();
                helperListener.SERVICE_REGISTERED(serviceInfo);
            }

            @Override
            public void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode)
            {
                helperListener.SERVICE_REGISTRATION_FAILED(serviceInfo, errorCode);
            }

            @Override
            public void onServiceUnregistered(NsdServiceInfo serviceInfo)
            {
                helperListener.SERVICE_UNREGISTERED(serviceInfo);
            }

            @Override
            public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode)
            {
                helperListener.SERVICE_UNREGISTRATION_FAILED(serviceInfo, errorCode);
            }

        };
    }

    /**
     * To be called after initialize()
     * 
     * @param port
     *            - the port you would like to register/broadcast the service through.
     */
    public void registerService(int port)
    {
        NsdServiceInfo serviceInfo = new NsdServiceInfo();
        serviceInfo.setPort(port);
        serviceInfo.setServiceName(mServiceName);
        serviceInfo.setServiceType(SERVICE_TYPE);

        mNsdManager.registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD, mRegistrationListener);

    }

    /**
     * Initiate service discovery to browse for instances of a service type. Service discovery consumes network bandwidth and will continue
     * until the application calls stopServiceDiscovery(NsdManager.DiscoveryListener).
     */
    public void discoverServices()
    {
        mNsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
    }

    /**
     * Stop service discovery initiated with discoverServices(String, int, NsdManager.DiscoveryListener). An active service discovery is
     * notified to the application with onDiscoveryStarted(String) and it stays active until the application invokes a stop service
     * discovery. A successful stop is notified to with a call to onDiscoveryStopped(String).
     */
    public void stopDiscovery()
    {
        mNsdManager.stopServiceDiscovery(mDiscoveryListener);
    }

    /**
     * 
     * @return - A class representing service information for network service discovery
     */
    public NsdServiceInfo getChosenServiceInfo()
    {
        return mService;
    }

    /**
     * Unregister a service registered through registerService(NsdServiceInfo, int, NsdManager.RegistrationListener). A successful
     * unregister is notified to the application with a call to onServiceUnregistered(NsdServiceInfo).
     */
    public void tearDown()
    {
        if (mNsdManager != null)
        {
            try
            {
                mNsdManager.unregisterService(mRegistrationListener);
                mNsdManager.stopServiceDiscovery(mDiscoveryListener);
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }

    /**
     * 
     * @return - the DiscoveredDevicesManager that contains all valid devices which have the appropriate service susally will call this
     *         after a msg of RESOLVE_SUCCESS
     */
    public DiscoveredDevicesManager getDeviceManager()
    {
        return deviceManager;
    }

}

最后這是服務器的基礎

    @Override
    public void run()
    {
        try
        {
            receiverSocket = new ServerSocket(0);

            onPortObtained(receiverSocket.getLocalPort());

            Log.d(TAG, "run");
            while (broadcastConnection)
            {
                try
                {
                    Socket newConnectionSocket = receiverSocket.accept();
                    onNewConnection(newConnectionSocket.getRemoteSocketAddress(), newConnectionSocket.getLocalSocketAddress());
                                    // to clarify this line launches a function that starts threads to handle the socket.
                    recieveConnection(newConnectionSocket);

                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }
        catch (IOException e1)
        {
            e1.printStackTrace();
        }
    }

編輯:還有一件事,有時在運行設備時會隨機重啟。 沒什么大不了的,除了他們正在運行應用程序。

由於服務發現將很難處理,因此我將通過執行這樣的初始ping來構建自己的發現

        List<DiscoveredDevice> devices = new ArrayList<DiscoveredDevice>();
        for (int i = 0; i < 256; i++)
        {
            // this hardcoded ip will be variable from the wifi's ip
            String ip = "xx.xx.x." + i;
            // this socket may be forever hard coded unless i find a better way. :(
            devices.add(new DiscoveredDevice(32999, ip, "", ""));
        }

點擊所有設備,注冊每個接受的設備,以及每個接受注冊的設備。

離開時,它將調度從每個設備隊列中刪除的命令,並且在嘗試發送設備時,未被接受的連接將被刪除。

有點黑,但是Android的方式對我不起作用:(,而且這種方式效果很好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM