我正在把头撞在墙上。它有效,但不起作用。
让我澄清一下,测试是在LG Optimus G,A Galaxy S4和联想平板电脑上运行4.1 +
我在每个设备上启动一个服务器,每个设备在一个端口上自己广播,当用户点击发送时,所有已经解析了服务并且服务没有丢失的设备,一个线程将循环启动其他线程连接到自己广播的服务器,并发送数据。服务器接受传入连接,将其交给线程,然后重新打开。
所以回顾一下,每个设备都在广播服务器,每个设备都应该知道并跟踪其他服务器,当数据被发送时,所有已知服务器都会被命中。
我的问题是,在2/3设备中,可以始终与设备的自身建立连接。
两部手机,但一次只有一部,似乎知道另一部手机,并能够连接到另一部手机。即Galaxy S4可以向Optimus G打招呼,但是Optimus G除了自己或副歌之外不能说喜。
所以发现部分似乎不可靠,我不知道它是我,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();
}
}
编辑:还有一件事,有时在运行设备时会随机重启。没有常见的事情导致,除此之外他们正在运行应用程序。
答案 0 :(得分: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的方式并不适合我:(,这种方式非常有效。