0

我正用头撞墙。它有效,但它不起作用。

让我澄清一下,测试是在运行 4.1+ 的 LG Optimus G、Galaxy S4 和联想平板电脑上进行的

我在每个设备上启动一个服务器,每个设备都在一个端口上广播自己,当用户点击发送时,所有已经解决了他们的服务并且他们的服务没有丢失的设备,一个线程将循环启动其他线程到连接到广播自己的服务器,并发送数据。服务器接受传入的连接,将其交给一个线程,然后重新打开它们自己。

回顾一下,每个设备都在广播服务器,每个设备都应该知道并跟踪其他服务器,当发送数据时,所有已知的服务器都会受到攻击。

我的问题是,在 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();
        }
    }

编辑:还有一件事,有时在运行设备时会随机重启。没有常见的原因,除此之外他们正在运行该应用程序。

4

1 回答 1

0

由于服务发现很难处理,我将通过像这样进行初始 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, "", ""));
        }

点击所有设备,注册每个接受的设备,以及接受注册它的每个设备。

在离开时,它将发送一个命令以从每个设备队列中删除,并且在尝试向设备发送不被接受的连接时,它将被删除。

Hackish,但 Android 方式对我不起作用 :(,而且这种方式效果很好。

于 2013-05-25T05:34:29.483 回答