उपलब्धता के लिए एक HTTP URL को पिंग करने के लिए पसंदीदा जावा तरीका


157

मुझे एक मॉनिटर क्लास की आवश्यकता है जो नियमित रूप से जाँचता है कि क्या एक दिया गया HTTP URL उपलब्ध है। मैं स्प्रिंग टास्क एक्ससर्चर अमूर्त का उपयोग करके "नियमित रूप से" भाग की देखभाल कर सकता हूं, इसलिए यहां यह विषय नहीं है। सवाल यह है कि जावा में URL पिंग करने का पसंदीदा तरीका क्या है?

यहाँ एक प्रारंभिक बिंदु के रूप में मेरा वर्तमान कोड है:

try {
    final URLConnection connection = new URL(url).openConnection();
    connection.connect();
    LOG.info("Service " + url + " available, yeah!");
    available = true;
} catch (final MalformedURLException e) {
    throw new IllegalStateException("Bad URL: " + url, e);
} catch (final IOException e) {
    LOG.info("Service " + url + " unavailable, oh no!", e);
    available = false;
}
  1. क्या यह बिल्कुल अच्छा है (क्या यह वही होगा जो मैं चाहता हूं)?
  2. क्या मुझे किसी तरह कनेक्शन बंद करना है?
  3. मुझे लगता है कि यह एक GETअनुरोध है। क्या HEADइसके बजाय भेजने का कोई तरीका है ?

जवाबों:


267

क्या यह बिल्कुल अच्छा है (क्या यह वही होगा जो मैं चाहता हूं?)

आप ऐसा कर सकते हैं। एक और संभव तरीका उपयोग कर रहा है java.net.Socket

public static boolean pingHost(String host, int port, int timeout) {
    try (Socket socket = new Socket()) {
        socket.connect(new InetSocketAddress(host, port), timeout);
        return true;
    } catch (IOException e) {
        return false; // Either timeout or unreachable or failed DNS lookup.
    }
}

वहाँ भी है InetAddress#isReachable():

boolean reachable = InetAddress.getByName(hostname).isReachable();

हालांकि यह स्पष्ट रूप से पोर्ट 80 का परीक्षण नहीं करता है। फ़ायरवॉल के कारण अन्य पोर्ट को अवरुद्ध करने के कारण आपको गलत नकारात्मक का खतरा होता है।


क्या मुझे किसी तरह कनेक्शन बंद करना है?

नहीं, आपको स्पष्ट रूप से आवश्यकता नहीं है। यह संभाला और हुड के नीचे जमा है।


मुझे लगता है कि यह एक GET अनुरोध है। क्या इसके बजाय HEAD भेजने का कोई तरीका है?

आप प्राप्त डाल सकता URLConnectionकरने के लिए HttpURLConnectionऔर उसके बाद का उपयोग setRequestMethod()अनुरोध विधि सेट करने के लिए। हालाँकि, आपको इस बात का ध्यान रखना होगा कि कुछ खराब वेबएप या होमग्राउन सर्वर HTTP 405 एरर को HEAD (यानी उपलब्ध नहीं, लागू नहीं, लागू नहीं) के लिए लौटा सकते हैं जबकि GET पूरी तरह से ठीक काम करता है। यदि आप लिंक / संसाधनों को सत्यापित करने का इरादा नहीं रखते हैं तो GET का उपयोग करना अधिक विश्वसनीय है।


उपलब्धता के लिए सर्वर का परीक्षण करना मेरे मामले में पर्याप्त नहीं है, मुझे URL का परीक्षण करने की आवश्यकता है (वेबएप की तैनाती नहीं की जा सकती)

दरअसल, किसी होस्ट को कनेक्ट करना केवल तभी सूचित करता है जब होस्ट उपलब्ध हो, न कि कंटेंट उपलब्ध हो। यह अच्छा हो सकता है कि एक वेबसर्वर बिना किसी समस्या के शुरू हो गया है, लेकिन सर्वर की शुरुआत के दौरान वेबैप तैनात करने में विफल रहा। हालांकि यह आमतौर पर पूरे सर्वर को कम करने का कारण नहीं होगा। आप यह निर्धारित कर सकते हैं कि HTTP प्रतिसाद कोड 200 है या नहीं।

HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestMethod("HEAD");
int responseCode = connection.getResponseCode();
if (responseCode != 200) {
    // Not OK.
}

// < 100 is undetermined.
// 1nn is informal (shouldn't happen on a GET/HEAD)
// 2nn is success
// 3nn is redirect
// 4nn is client error
// 5nn is server error

प्रतिक्रिया स्थिति कोड के बारे में अधिक विस्तार के लिए RFC 2616 अनुभाग 10 देखेंconnect()यदि आप प्रतिक्रिया डेटा का निर्धारण कर रहे हैं तो कॉलिंग की आवश्यकता नहीं है। यह अंतर्निहित रूप से जुड़ेगा।

भविष्य के संदर्भ के लिए, यहाँ एक उपयोगिता विधि के स्वाद में एक पूर्ण उदाहरण है, समयबाह्य के साथ खाता भी:

/**
 * Pings a HTTP URL. This effectively sends a HEAD request and returns <code>true</code> if the response code is in 
 * the 200-399 range.
 * @param url The HTTP URL to be pinged.
 * @param timeout The timeout in millis for both the connection timeout and the response read timeout. Note that
 * the total timeout is effectively two times the given timeout.
 * @return <code>true</code> if the given HTTP URL has returned response code 200-399 on a HEAD request within the
 * given timeout, otherwise <code>false</code>.
 */
public static boolean pingURL(String url, int timeout) {
    url = url.replaceFirst("^https", "http"); // Otherwise an exception may be thrown on invalid SSL certificates.

    try {
        HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
        connection.setConnectTimeout(timeout);
        connection.setReadTimeout(timeout);
        connection.setRequestMethod("HEAD");
        int responseCode = connection.getResponseCode();
        return (200 <= responseCode && responseCode <= 399);
    } catch (IOException exception) {
        return false;
    }
}

3
विवरण के लिए धन्यवाद, इस तरह के उत्तर एसओ एक महान जगह बनाते हैं। उपलब्धता के लिए सर्वर का परीक्षण करना मेरे मामले में पर्याप्त नहीं है, मुझे URL का परीक्षण करने की आवश्यकता है (वेबप को लागू नहीं किया जा सकता है), इसलिए मैं HttpURLConnection के साथ रहूंगा। HEAD के बारे में एक अच्छा परीक्षण नहीं है: यह एक अच्छा तरीका है अगर मुझे पता है कि लक्ष्य URL HEAD का समर्थन करता है, तो मैं इसकी जाँच करूँगा।
शॉन पैट्रिक फ्लोयड

1
Java.io.IOException प्राप्त करना संभव है : कुछ सर्वरों पर स्ट्रीम का अप्रत्याशित अंत , इसे ठीक करने के लिए आपको connection.setRequestProperty ("Accept-Encoding", "musixmatch") जोड़ना होगा; यह ज्ञात समस्या है और code.google.com
Marcin Waowsniowski

1
@BalusC क्योंकि (200 <= responseCode && responseCode <= 399) सही होगा यदि और केवल यदि (प्रतिक्रिया <= 399), जिसका अर्थ है कि (200 <= responseCode) स्थिति बेमानी है। तो मुझे लगा कि गलती हो गई।
मेटेटर

4
@ मीटर: हुह ??? यह बिल्कुल बेमानी नहीं है। 200 से कम रिस्पांस कोड मान्य नहीं माने जाते हैं।
बालूसी

1
@BalusC Im कुछ स्थिति ये तरीका लगता है कि अच्छी तरह से काम नहीं करता है। यहां एक नज़र डालें stackoverflow.com/questions/25805580/…
AndreaF

17

इसके बजाय URLConnection उपयोग का उपयोग करने का HttpURLConnection अपने URL वस्तु पर openConnection () कॉल करके।

फिर कनेक्शन से पढ़ते ही getResponseCode () का उपयोग करके आपको HTTP रिस्पांस मिलेगा।

यहाँ कोड है:

    HttpURLConnection connection = null;
    try {
        URL u = new URL("http://www.google.com/");
        connection = (HttpURLConnection) u.openConnection();
        connection.setRequestMethod("HEAD");
        int code = connection.getResponseCode();
        System.out.println("" + code);
        // You can determine on HTTP return code received. 200 is success.
    } catch (MalformedURLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } finally {
        if (connection != null) {
            connection.disconnect();
        }
    }

यह भी इसी तरह के प्रश्न की जांच करें कि यदि कोई URL मौजूद है या जावा के साथ 404 रिटर्न कैसे जांचें?

उम्मीद है की यह मदद करेगा।


7

आप HttpURLConnection का भी उपयोग कर सकते हैं , जो आपको अनुरोध विधि (उदाहरण के लिए HEAD) सेट करने की अनुमति देता है। यहां एक उदाहरण है जो दिखाता है कि अनुरोध कैसे भेजें, प्रतिक्रिया पढ़ें और डिस्कनेक्ट करें।


4

निम्न कोड HEADयह जांचने का अनुरोध करता है कि वेबसाइट उपलब्ध है या नहीं।

public static boolean isReachable(String targetUrl) throws IOException
{
    HttpURLConnection httpUrlConnection = (HttpURLConnection) new URL(
            targetUrl).openConnection();
    httpUrlConnection.setRequestMethod("HEAD");

    try
    {
        int responseCode = httpUrlConnection.getResponseCode();

        return responseCode == HttpURLConnection.HTTP_OK;
    } catch (UnknownHostException noInternetConnection)
    {
        return false;
    }
}

4

यहाँ लेखक यह सुझाव देता है:

public boolean isOnline() {
    Runtime runtime = Runtime.getRuntime();
    try {
        Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
        int     exitValue = ipProcess.waitFor();
        return (exitValue == 0);
    } catch (IOException | InterruptedException e) { e.printStackTrace(); }
    return false;
}

संभव प्रश्न

  • क्या यह वास्तव में काफी तेज है? हां, बहुत तेजी से!
  • क्या मैं सिर्फ अपना ही पेज पिंग नहीं कर सकता, जिसे मैं वैसे भी अनुरोध करना चाहता हूं? ज़रूर! यदि आप "इंटरनेट कनेक्शन उपलब्ध" और अपने स्वयं के सर्वर के बीच अंतर करना चाहते हैं, तो भी आप दोनों की जांच कर सकते हैं, यदि DNS नीचे है तो क्या होगा? Google DNS (जैसे 8.8.8.8) दुनिया की सबसे बड़ी सार्वजनिक DNS सेवा है। 2013 तक यह एक दिन में 130 बिलियन अनुरोधों पर कार्य करता है। चलो बस कहना है, आपके एप्लिकेशन का जवाब नहीं है शायद दिन की बात नहीं होगी।

लिंक पढ़ें। यह बहुत अच्छा लगता है

संपादित करें: इसका उपयोग करने के मेरे विस्तार में, यह इस पद्धति की तरह तेज़ नहीं है:

public boolean isOnline() {
    NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo();
    return netInfo != null && netInfo.isConnectedOrConnecting();
}

वे थोड़े अलग हैं लेकिन इंटरनेट से कनेक्शन की जाँच के लिए कार्यक्षमता में पहला तरीका कनेक्शन चर के कारण धीमा हो सकता है।


2

रेस्टलेट ढांचे का उपयोग करने पर विचार करें, जिसमें इस तरह की चीजों के लिए बहुत शब्दार्थ है। यह शक्तिशाली और लचीला है।

कोड उतना ही सरल हो सकता है:

Client client = new Client(Protocol.HTTP);
Response response = client.get(url);
if (response.getStatus().isError()) {
    // uh oh!
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.