InetAddress byName = InetAddress.getByName("173.39.161.140");
System.out.println(byName);
System.out.println(byName.isReachable(1000));
จะisReachable
กลับมาทำไมfalse
? ฉันสามารถ ping IP
InetAddress byName = InetAddress.getByName("173.39.161.140");
System.out.println(byName);
System.out.println(byName.isReachable(1000));
จะisReachable
กลับมาทำไมfalse
? ฉันสามารถ ping IP
คำตอบ:
วิธี"isReachable"ไม่สมควรใช้สำหรับฉันในหลาย ๆ กรณี คุณสามารถเลื่อนลงไปด้านล่างเพื่อดูทางเลือกของฉันสำหรับการทดสอบว่าคุณออนไลน์และสามารถแก้ไขโฮสต์ภายนอกได้ (เช่น google.com) ... ซึ่งโดยทั่วไปดูเหมือนว่าจะทำงานบนเครื่อง * NIX
ปัญหา
มีการพูดพล่อยมากมายเกี่ยวกับเรื่องนี้:
คำถามอื่น ๆ ที่คล้ายกันมีดังนี้
และแม้แต่รายงานข้อผิดพลาดในเรื่องเดียวกันนี้:
ส่วนที่ 1: ตัวอย่างที่ทำซ้ำได้ของปัญหา
โปรดทราบว่าในกรณีนี้ล้มเหลว
//also, this fails for an invalid address, like "www.sjdosgoogle.com1234sd"
InetAddress[] addresses = InetAddress.getAllByName("www.google.com");
for (InetAddress address : addresses) {
if (address.isReachable(10000))
{
System.out.println("Connected "+ address);
}
else
{
System.out.println("Failed "+address);
}
}
//output:*Failed www.google.com/74.125.227.114*
ส่วนที่ 2: วิธีแก้ปัญหาแฮ็ก
คุณสามารถทำได้โดยทำดังนี้
// in case of Linux change the 'n' to 'c'
Process p1 = java.lang.Runtime.getRuntime().exec("ping -n 1 www.google.com");
int returnVal = p1.waitFor();
boolean reachable = (returnVal==0);
ตัวเลือก -c ของpingจะช่วยให้ ping พยายามเข้าถึงเซิร์ฟเวอร์เพียงครั้งเดียว (ตรงข้ามกับ ping ที่ไม่มีที่สิ้นสุดซึ่งเราคุ้นเคยกับการใช้ที่เทอร์มินัล)
นี้จะกลับ0 ถ้าโฮสต์สามารถเข้าถึงได้ มิฉะนั้นคุณจะได้รับ "2" เป็นค่าตอบแทน
ง่ายกว่ามาก - แต่แน่นอนว่าเป็นแพลตฟอร์มเฉพาะ และอาจมีข้อควรระวังเกี่ยวกับสิทธิพิเศษบางประการในการใช้คำสั่งนี้ - แต่ฉันพบว่ามันใช้ได้กับเครื่องของฉัน
โปรดทราบว่า: 1) การแก้ปัญหานี้ไม่ใช่คุณภาพการผลิต มันเป็นการแฮ็กเล็กน้อย หาก Google หยุดทำงานหรืออินเทอร์เน็ตของคุณช้าชั่วคราวหรืออาจถึงแม้จะมีความสนุกสนานในการตั้งค่าสิทธิ์ / ระบบของคุณหากสามารถส่งคืนค่าลบเท็จ (กล่าวคืออาจล้มเหลวแม้ว่าที่อยู่ที่ป้อนจะเข้าถึงได้) 2) ความล้มเหลว isReachable เป็นปัญหาที่โดดเด่น อีกครั้ง - มีแหล่งข้อมูลออนไลน์มากมายที่ระบุว่าไม่มีวิธีที่ "สมบูรณ์แบบ" ในการดำเนินการนี้ในขณะที่เขียนนี้เนื่องจากวิธีที่ JVM พยายามเข้าถึงโฮสต์ - ฉันเดาว่ามันเป็นงานเฉพาะของแพลตฟอร์มที่อยู่ภายในซึ่งแม้ว่าจะเรียบง่าย ยังไม่ได้รับการสรุปอย่างเพียงพอโดย JVM
isReachable
ฉันล้มเหลวและใช้ ping ฉันได้รับ icmp ไม่ได้รับอนุญาต? คุณรู้วิธีจัดการกับมันตอนนี้หรือไม่?
public boolean waitFor(long timeout, TimeUnit unit)
ใน java.lang.Process (@since 1.8)
isReachable
มีความน่าเชื่อถือมากขึ้นในปัจจุบัน
ฉันมาที่นี่เพื่อรับคำตอบสำหรับคำถามเดียวกันนี้ แต่ฉันไม่พอใจกับคำตอบใด ๆ เพราะฉันกำลังมองหาโซลูชันที่เป็นอิสระจากแพลตฟอร์ม นี่คือรหัสที่ฉันเขียนและเป็นแพลตฟอร์มที่ไม่ขึ้นกับแพลตฟอร์ม แต่ต้องการข้อมูลเกี่ยวกับพอร์ตที่เปิดบนเครื่องอื่น (ซึ่งเรามีอยู่เกือบตลอดเวลา)
private static boolean isReachable(String addr, int openPort, int timeOutMillis) {
// Any Open port on other machine
// openPort = 22 - ssh, 80 or 443 - webserver, 25 - mailserver etc.
try {
try (Socket soc = new Socket()) {
soc.connect(new InetSocketAddress(addr, openPort), timeOutMillis);
}
return true;
} catch (IOException ex) {
return false;
}
}
InetAddress.isReachable()
อยู่แล้วผ่านพอร์ต 7 ยกเว้นว่าตัวหลังฉลาดกว่าเกี่ยวกับความIOExceptions
หมายที่เป็นไปได้ต่างๆในแง่ของความสามารถในการเข้าถึง
InetAddress.isReachable()
มีการใส่อาร์กิวเมนต์พอร์ตมากเกินไปในไลบรารีมาตรฐาน ฉันสงสัยว่าทำไมมันไม่รวม?
หากคุณต้องการตรวจสอบว่าเชื่อมต่อกับอินเทอร์เน็ตหรือไม่ให้ใช้วิธีนี้มันจะคืนค่าจริงหากเชื่อมต่ออินเทอร์เน็ตจะดีกว่าถ้าคุณใช้ที่อยู่ของไซต์ที่คุณพยายามเชื่อมต่อผ่านโปรแกรม
public static boolean isInternetReachable()
{
try {
//make a URL to a known source
URL url = new URL("http://www.google.com");
//open a connection to that source
HttpURLConnection urlConnect = (HttpURLConnection)url.openConnection();
//trying to retrieve data from the source. If there
//is no connection, this line will fail
Object objData = urlConnect.getContent();
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
เพียงแค่พูดอย่างชัดเจนเนื่องจากคำตอบอื่น ๆ ไม่มี ส่วน ping ของ isReachable () ต้องการการเข้าถึงรูทบน Unix และตามที่ bestsss ชี้ให้เห็นใน4779367 :
และถ้าคุณถามว่าทำไม ping จาก bash ไม่ได้จริงๆแล้วมันก็ต้องการเช่นกัน ทำเช่นนั้น ls -l / bin / ping
เนื่องจากการใช้ root ไม่ใช่ตัวเลือกในกรณีของฉันวิธีแก้ปัญหาคืออนุญาตให้เข้าถึงพอร์ต 7 ในไฟร์วอลล์ไปยังเซิร์ฟเวอร์เฉพาะที่ฉันสนใจ
ฉันไม่แน่ใจว่าสถานะเป็นอย่างไรเมื่อคำถามเดิมถูกถามกลับในปี 2555
ในขณะนี้ ping จะดำเนินการในฐานะรูท ผ่านการอนุญาตของ ping ที่เรียกใช้งานได้คุณจะเห็นแฟล็ก + s และกระบวนการที่เป็นของ root ซึ่งหมายความว่ามันจะทำงานเป็น root เรียกใช้ ls -liat ที่ตำแหน่ง ping และคุณจะเห็น
ดังนั้นหากคุณเรียกใช้ InetAddress.getByName ("www.google.com") isReacheable (5000) เป็นรูทก็ควรคืนค่าจริง
คุณต้องมีการอนุญาตที่เหมาะสมสำหรับซ็อกเก็ตดิบซึ่ง ICMP ใช้ (โปรโตคอลที่ใช้โดย ping)
InetAddress.getByName มีความน่าเชื่อถือพอ ๆ กับ ping แต่คุณต้องมีสิทธิ์ที่เหมาะสมในกระบวนการเพื่อให้มันทำงานได้อย่างถูกต้อง
เนื่องจากคุณสามารถ ping คอมพิวเตอร์ได้กระบวนการ Java ของคุณควรทำงานโดยมีสิทธิ์เพียงพอที่จะทำการตรวจสอบ น่าจะเกิดจากการใช้พอร์ตในช่วงล่าง หากคุณรันโปรแกรม java ด้วย sudo / superuser ฉันจะพนันได้เลยว่ามันใช้ได้
ฉันขอแนะนำว่าวิธีเดียวที่เชื่อถือได้ในการทดสอบการเชื่อมต่ออินเทอร์เน็ตคือการเชื่อมต่อและดาวน์โหลดไฟล์จริง ๆ หรือเพื่อแยกวิเคราะห์ผลลัพธ์ของการโทร ping ของระบบปฏิบัติการผ่าน exec () คุณไม่สามารถพึ่งพารหัสทางออกสำหรับ ping และ isReachable () คืออึ
คุณไม่สามารถพึ่งพารหัสออกจาก ping ได้เนื่องจากจะส่งกลับ 0 หากคำสั่ง ping ดำเนินการอย่างถูกต้อง น่าเสียดายที่ ping ดำเนินการอย่างถูกต้องหากไม่สามารถเข้าถึงโฮสต์เป้าหมาย แต่ได้รับ "โฮสต์ปลายทางที่ไม่สามารถเข้าถึงได้" จากเราเตอร์ ADSL ที่บ้านของคุณ นี่เป็นการตอบกลับที่ถือว่าเป็น Hit ที่สำเร็จดังนั้น exit code = 0 ต้องเพิ่มแม้ว่านี่จะอยู่ในระบบ Windows ไม่ได้ตรวจสอบ * nixes
private boolean isReachable(int nping, int wping, String ipping) throws Exception {
int nReceived = 0;
int nLost = 0;
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("ping -n " + nping + " -w " + wping + " " + ipping);
Scanner scanner = new Scanner(process.getInputStream());
process.waitFor();
ArrayList<String> strings = new ArrayList<>();
String data = "";
//
while (scanner.hasNextLine()) {
String string = scanner.nextLine();
data = data + string + "\n";
strings.add(string);
}
if (data.contains("IP address must be specified.")
|| (data.contains("Ping request could not find host " + ipping + ".")
|| data.contains("Please check the name and try again."))) {
throw new Exception(data);
} else if (nping > strings.size()) {
throw new Exception(data);
}
int index = 2;
for (int i = index; i < nping + index; i++) {
String string = strings.get(i);
if (string.contains("Destination host unreachable.")) {
nLost++;
} else if (string.contains("Request timed out.")) {
nLost++;
} else if (string.contains("bytes") && string.contains("time") && string.contains("TTL")) {
nReceived++;
} else {
}
}
return nReceived > 0;
}
nping คือจำนวนการพยายาม ping ip (แพ็กเก็ต) หากคุณมีเครือข่ายหรือระบบไม่ว่างให้เลือกหมายเลข nping ที่ใหญ่กว่า
wping เป็นเวลารอ pong จาก ip คุณสามารถตั้งค่าได้ 2000ms
สำหรับการใช้วิธีนี้คุณสามารถเขียนสิ่งนี้:
isReachable(5, 2000, "192.168.7.93");
หรือใช้วิธีนี้:
public static boolean exists(final String host)
{
try
{
InetAddress.getByName(host);
return true;
}
catch (final UnknownHostException exception)
{
exception.printStackTrace();
// Handler
}
return false;
}
InetAddress.isReachable
เครื่องปัดและบางครั้งกลับไม่สามารถเข้าถึงได้สำหรับที่อยู่ซึ่งเราสามารถ ping ได้
ฉันลองทำสิ่งต่อไปนี้:
ping -c 1 <fqdn>
และตรวจสอบไฟล์exit status
.
ใช้ได้กับทุกกรณีที่ฉันลองแล้วInetAddress.isReachable
ไม่ได้ผล