[英]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.