[英]java: Good socket timeout for LAN connections?
我有一台服務器(在我的筆記本電腦上運行的Java應用程序)和一個客戶端(在我的Android智能手機上運行的Java應用程序 我正在嘗試從我的客戶端自動查找服務器的IP地址 。
現在我只是循環所有IP在同一個局域網(192.168.1.0> 192.168.1.1.255),如果服務器(正在監聽自定義端口)接受連接,那么我找到了IP。
問題是,如果我設置連接超時少於200毫秒,大多數時候客戶端找不到服務器。
所以問題是,我如何實現更好(更快)的方式來查找服務器IP? 我嘗試過java InetAddress.isReachable()方法,但服務器似乎總是無法訪問...
並且,如果沒有更好的方法,您認為本地(LAN)套接字連接的超時值是多少?
只是為了其他人...我剛剛找到了一個非常好的方法來找到服務器IP,然后再少一半!
我的解決方案:
String partialIp = "192.168.1.";
int port = 123;
int counter;
boolean found;
String ip;
Runnable tryNextIp = new Runnable() {
@Override
public void run() {
int myIp = counter++;
String targetIpTemp = partialIp + myIp;
Socket socketTemp = new Socket();
try {
socketTemp.connect(new InetSocketAddress(targetIpTemp, port), 6000);
socketTemp.close();
ip = targetIpTemp;
found = true;
} catch (IOException e) {
try {
socketTemp.close();
} catch (IOException e1) {}
}
}
};
String findIp() {
counter = 0;
found = false;
ExecutorService executorService = Executors.newFixedThreadPool(256);
for (int i=0; i<256; i++) {
if (found)
break;
executorService.execute(tryNextIp);
}
executorService.shutdown();
try {
while (!found && !executorService.isTerminated())
executorService.awaitTermination(200, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {}
if (found)
return ip;
else
return null;
}
考慮到典型的網絡條件和服務器響應時間,良好的超時值是您願意等待服務器回復的時間。 您需要選擇一個合理的值,與您的應用程序無關 - 由您決定如果服務器在X時間內沒有響應,那么可以安全地假設它不在那里。
要加速客戶端,請考慮創建多個線程以一次查詢多個服務器。 Executors.newFixedThreadPool()
會讓你無所適從。
但是,您可能需要考慮其他不需要完整網絡掃描的替代方案; 例如:
只需讓用戶/管理員指定IP地址( 為什么需要發現服務器IP?你不知道你在服務器上設置了什么機器?為什么不將服務器配置為具有靜態LAN IP?)
如果您確實需要服務發現,NSD / Zeroconf / Bonjour等技術可以進行服務廣告和發現。
即使是非常基本的東西也可能適合您的需求,例如從客戶端發送廣播UDP數據包並讓服務器響應,或讓服務器定期廣播通知。
套接字超時應該完全取決於請求的預期服務時間。 天真地你可以找到平均服務時間並使用雙倍超時。 如果你想要更准確,你需要繪制服務時間的統計分布,確定標准偏差,並使用平均值加上標准差的三倍甚至四倍作為超時,以確保你沒有得到假陽性超時但您確實在合理的時間內檢測到了失敗。 最終,它取決於你想要的觸發快樂程度。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.