क्या आप HttpURLConnection कनेक्शन प्रक्रिया की व्याख्या कर सकते हैं?


134

मैं HTTPURLConnectionएक वेब सेवा से जुड़ने के लिए उपयोग कर रहा हूं । मुझे पता है कि कैसे उपयोग करना है HTTPURLConnectionलेकिन मैं समझना चाहता हूं कि यह कैसे काम करता है। मूल रूप से, मैं निम्नलिखित जानना चाहता हूं:

  • किस बिंदु पर HTTPURLConnectionदिए गए URL से संबंध स्थापित करने का प्रयास किया जाता है?
  • मुझे किस बिंदु पर पता चल सकता है कि मैं सफलतापूर्वक कनेक्शन स्थापित करने में सक्षम था?
  • क्या एक कनेक्शन स्थापित कर रहे हैं और एक चरण / विधि कॉल में किए गए वास्तविक अनुरोध भेज रहे हैं? क्या विधि है?
  • क्या आप आम आदमी के कार्यकाल में getOutputStreamऔर उसके कार्य की व्याख्या कर सकते हैं getInputStream? मुझे लगता है कि जब सर्वर मैं कनेक्ट करने के लिए कोशिश कर रहा हूँ नीचे है, मैं एक Exceptionपर मिलता है getOutputStream। क्या इसका मतलब यह है कि HTTPURLConnectionजब मैं आह्वान करूंगा तो केवल एक संबंध स्थापित करना शुरू कर दूंगा getOutputStream? कैसे के बारे में getInputStream? चूंकि मैं केवल प्रतिक्रिया प्राप्त करने में सक्षम हूं getInputStream, तो क्या इसका मतलब है कि मैंने getOutputStreamअभी तक कोई अनुरोध नहीं भेजा है, लेकिन बस एक कनेक्शन स्थापित करता है? क्या HttpURLConnectionप्रतिक्रिया के लिए अनुरोध करने के लिए सर्वर के लिए जाने के लिए वापस जब मैं आह्वान getInputStream?
  • क्या मैं यह कहना सही हूं कि openConnectionबस एक नया कनेक्शन ऑब्जेक्ट बनाता है लेकिन अभी तक कोई कनेक्शन स्थापित नहीं करता है?
  • मैं रीड ओवरहेड को कैसे माप सकता हूं और ओवरहेड को कनेक्ट कर सकता हूं?

जवाबों:


184
String message = URLEncoder.encode("my message", "UTF-8");

try {
    // instantiate the URL object with the target URL of the resource to
    // request
    URL url = new URL("http://www.example.com/comment");

    // instantiate the HttpURLConnection with the URL object - A new
    // connection is opened every time by calling the openConnection
    // method of the protocol handler for this URL.
    // 1. This is the point where the connection is opened.
    HttpURLConnection connection = (HttpURLConnection) url
            .openConnection();
    // set connection output to true
    connection.setDoOutput(true);
    // instead of a GET, we're going to send using method="POST"
    connection.setRequestMethod("POST");

    // instantiate OutputStreamWriter using the output stream, returned
    // from getOutputStream, that writes to this connection.
    // 2. This is the point where you'll know if the connection was
    // successfully established. If an I/O error occurs while creating
    // the output stream, you'll see an IOException.
    OutputStreamWriter writer = new OutputStreamWriter(
            connection.getOutputStream());

    // write data to the connection. This is data that you are sending
    // to the server
    // 3. No. Sending the data is conducted here. We established the
    // connection with getOutputStream
    writer.write("message=" + message);

    // Closes this output stream and releases any system resources
    // associated with this stream. At this point, we've sent all the
    // data. Only the outputStream is closed at this point, not the
    // actual connection
    writer.close();
    // if there is a response code AND that response code is 200 OK, do
    // stuff in the first if block
    if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
        // OK

        // otherwise, if any other status code is returned, or no status
        // code is returned, do stuff in the else block
    } else {
        // Server returned HTTP error code.
    }
} catch (MalformedURLException e) {
    // ...
} catch (IOException e) {
    // ...
}

आपके सवालों के पहले 3 उत्तर प्रत्येक विधि के साथ इनलाइन टिप्पणियों के रूप में सूचीबद्ध हैं, उदाहरण के लिए ऊपर HTTP POST में।

से getOutputStream :

एक आउटपुट स्ट्रीम देता है जो इस कनेक्शन को लिखता है।

मूल रूप से, मुझे लगता है कि आपके पास यह समझने की अच्छी समझ है कि यह कैसे काम करता है, इसलिए मुझे आम आदमी की शर्तों को दोहराना चाहिए। सर्वर से डेटा लिखने के इरादे से getOutputStreamमूल रूप से एक कनेक्शन स्ट्रीम खोलता है । उपरोक्त कोड उदाहरण में "संदेश" एक टिप्पणी हो सकती है जो हम सर्वर पर भेज रहे हैं जो एक पोस्ट पर छोड़ी गई टिप्पणी का प्रतिनिधित्व करता है। जब आप देखते हैं getOutputStream, तो आप लेखन के लिए कनेक्शन स्ट्रीम खोल रहे हैं , लेकिन जब तक आप कॉल नहीं करते तब तक आप वास्तव में कोई डेटा नहीं लिखते हैं writer.write("message=" + message);

से getInputStream () :

एक इनपुट स्ट्रीम देता है जो इस खुले कनेक्शन से पढ़ता है। यदि पढ़ने के लिए डेटा उपलब्ध होने से पहले रीड टाइमआउट की समय सीमा समाप्त हो जाती है, तो रिटर्न इनपुट स्ट्रीम से पढ़ते समय एक सॉकेट टाइमआउट अपवाद को फेंका जा सकता है।

getInputStreamइसके विपरीत करता है। जैसे getOutputStream, यह एक कनेक्शन स्ट्रीम भी खोलता है , लेकिन इरादा सर्वर से डेटा पढ़ने का है, इसे लिखने का नहीं। यदि कनेक्शन या स्ट्रीम-ओपनिंग विफल हो जाती है, तो आप देखेंगे SocketTimeoutException

कैसे GetInputStream के बारे में? चूंकि मैं केवल getInputStream पर प्रतिक्रिया प्राप्त करने में सक्षम हूं, तो इसका मतलब यह है कि मैंने अभी तक getOutputStream पर कोई अनुरोध नहीं भेजा है, लेकिन बस एक कनेक्शन स्थापित करता है?

ध्यान रखें कि अनुरोध भेजना और डेटा भेजना दो अलग-अलग ऑपरेशन हैं। जब आप getOutputStream या getInputStream आह्वान करते हैं url.openConnection(), तो आप कनेक्शन स्थापित करने के लिए सर्वर को अनुरोध भेजते हैं। एक हैंडशेक है जो तब होता है जब सर्वर आपको एक पावती भेजता है कि कनेक्शन स्थापित है। यह उस समय है जब आप डेटा भेजने या प्राप्त करने के लिए तैयार हैं। इस प्रकार, आपको एक कनेक्शन खोलने के लिए getOutputStream को कॉल करने की आवश्यकता नहीं है , जब तक कि डेटा बनाने के लिए अनुरोध करने का आपका उद्देश्य नहीं है।

आम आदमी की शर्तों में, एक getInputStreamअनुरोध करना आपके दोस्त के घर पर फोन कॉल करने के बराबर है, "अरे, क्या यह ठीक है अगर मैं आता हूं और उस जोड़ी को कुलपतियों के रूप में उधार लेता हूं?" और आपका दोस्त यह कहकर हैंडशेक स्थापित करता है, "निश्चित! आओ और प्राप्त करो"। फिर, उस बिंदु पर, कनेक्शन बनाया जाता है, आप अपने दोस्त के घर पर चलते हैं, दरवाजे पर दस्तक देते हैं, वाइस ग्रिप का अनुरोध करते हैं, और अपने घर वापस चले जाते हैं।

इसी तरह के उदाहरण के लिए getOutputStreamअपने दोस्त को फोन करना और यह कहना कि "अरे, मेरे पास वह पैसा है जो मैं तुम्हें देना चाहता हूं, क्या मैं तुम्हें भेज सकता हूं"? आपके दोस्त को पैसे और बीमार की ज़रूरत है, जिसे आपने इसे लंबे समय तक रखा था, कहते हैं, "निश्चित रूप से, आप सस्ते कमीने पर आते हैं"। तो आप अपने दोस्त के घर चलें और उसके लिए "POST" करें। वह फिर आपको बाहर निकालता है और आप अपने घर वापस जाते हैं।

अब, आम आदमी के उदाहरण के साथ जारी, आइए कुछ अपवादों को देखें। यदि आपने अपने दोस्त को फोन किया और वह घर नहीं था, तो वह 500 त्रुटि हो सकती है। यदि आपने कॉल किया और डिस्कनेक्ट किया हुआ नंबर संदेश मिला क्योंकि आपका मित्र हर समय आपसे पैसे उधार लेता है, तो वह 404 पृष्ठ नहीं मिला। यदि आपका फोन मर चुका है क्योंकि आपने बिल का भुगतान नहीं किया है, तो वह IOException हो सकता है। (नोट: यह खंड १००% सही नहीं हो सकता है। इसका उद्देश्य आपको सामान्य विचार देना है कि आम आदमी की शर्तों में क्या हो रहा है।)

प्रश्न # 5:

हां, आप सही हैं कि ओपनकॉन्नेक्शन केवल एक नया कनेक्शन ऑब्जेक्ट बनाता है, लेकिन इसे स्थापित नहीं करता है। कनेक्शन स्थापित होता है जब आप या तो getInputStream या getOutputStream कहते हैं।

openConnectionएक नया कनेक्शन ऑब्जेक्ट बनाता है। से URL.openConnection javadocs :

इस URL के लिए प्रोटोकॉल हैंडलर की ओपनकॉन्च विधि को कॉल करके हर बार एक नया कनेक्शन खोला जाता है।

कनेक्शन की स्थापना तब की जाती है जब आप ओपनकॉइन कहते हैं, और इनपुटस्ट्रीम, आउटपुटस्ट्रीम, या दोनों, को बुलाया जाता है जब आप उन्हें इंस्टेंट करते हैं।

प्रश्न # 6 :

ओवरहेड को मापने के लिए, मैं आम तौर पर पूरे कनेक्शन ब्लॉक के आसपास कुछ बहुत ही सरल टाइमिंग कोड लपेटता हूं, जैसे:

long start = System.currentTimeMillis();
log.info("Time so far = " + new Long(System.currentTimeMillis() - start) );

// run the above example code here
log.info("Total time to send/receive data = " + new Long(System.currentTimeMillis() - start) );

मुझे यकीन है कि अनुरोध समय और ओवरहेड को मापने के लिए अधिक उन्नत तरीके हैं, लेकिन यह आम तौर पर मेरी जरूरतों के लिए पर्याप्त है।

कनेक्शन बंद करने के बारे में जानकारी के लिए, जिसके बारे में आपने नहीं पूछा, जावा में देखें कि URL कनेक्शन कब बंद होता है?


नमस्ते। धन्यवाद!!! यह वास्तव में एक विस्तृत विवरण था और मैं वास्तव में आपके उत्तर की सराहना करता हूं। यदि मैं आपके उत्तर को सही ढंग से समझता हूं, तो getOutputStream और getInputStream दोनों ही कनेक्शन स्थापित करते हैं यदि कोई कनेक्शन अभी तक स्थापित नहीं किया गया है। अगर मैं getOutputStream को कॉल करता हूं, तो getInputStream को कॉल करें, आंतरिक रूप से, HTTPURLConnection, getInputStream पर किसी कनेक्शन को पुनर्स्थापित नहीं कर रहा है क्योंकि मैं पहले से ही getOutStream पर इसे स्थापित करने में सक्षम था? HttpURLConnection पुनः प्राप्त करेगा जो भी कनेक्शन मैं getOutputStream को getInputStream में स्थापित करने में सक्षम था।
अरसी

Cont .: या यह getOutputStream और getInputStream के लिए एक नया और अलग कनेक्शन स्थापित करता है? इसके अलावा, अगर मैं कनेक्ट ओवरहेड प्राप्त करना चाहता हूं, तो मेरे टाइमर लगाने की उचित जगह getOutputStream से पहले और बाद में है। अगर मैं रीड ओवरहेड प्राप्त करना चाहता हूं, तो मेरे टाइमर लगाने की उचित जगह getInputStream से पहले और बाद में है।
Arci

याद रखें कि javadoc getInputStream और getOutputStream के बारे में क्या कहता है: Returns an output stream that writes to this connection.और Returns an input stream that reads from this open connection.। आउटपुटस्ट्रीम और इनपुटस्ट्रीम कनेक्शन से अलग हैं।
jmort253 5

8
यह ध्यान देने योग्य है कि ऐसा प्रतीत होता है कि HttpURLConnection ऑब्जेक्ट केवल उस बिंदु पर लक्ष्य URL तक पहुंचता है जिस पर ऐसा करना आवश्यक है। आपके उदाहरण में, आपके पास इनपुट और आउटपुट स्ट्रीम हैं, जो कनेक्शन खुलने तक निश्चित रूप से कुछ भी नहीं कर सकते हैं। एक बहुत सरल मामला एक GET ऑपरेशन है, जिसमें आप कनेक्शन शुरू करने के अलावा कुछ नहीं करते हैं और फिर प्रतिक्रिया कोड की जांच करते हैं। उस स्थिति में, कनेक्शन वास्तव में तब तक नहीं किया जाता है जब तक कि getResponseCode () विधि को नहीं कहा जाता है। अन्यथा, यह कनेक्शन जीवनचक्र की एक महान व्याख्या और अन्वेषण है!
स्पेंकी क्विगमैन

1
मैं 'UrlConnection' उदाहरण और अंतर्निहित Tcp / Ip / SSL कनेक्शन, 2 अलग-अलग अवधारणाओं के बीच भ्रमित था। पूर्व मूल रूप से एक HTTP पृष्ठ अनुरोध के साथ समानार्थी है। उत्तरार्द्ध कुछ ऐसा है जो उम्मीद है कि केवल एक बार ही बनाया जाएगा यदि आप एक ही सर्वर से कई पेज अनुरोध कर रहे हैं।
टिम कूपर

17

टिम ब्रे ने एक संक्षिप्त चरण-दर-चरण प्रस्तुत किया, जिसमें कहा गया कि ओपनकनेक्ट () एक वास्तविक कनेक्शन स्थापित नहीं करता है। जब तक आप getInputStream () या getOutputStream () जैसे तरीकों को कॉल नहीं करते, तब तक एक वास्तविक HTTP कनेक्शन स्थापित नहीं होता है।

http://www.tbray.org/ongoing/When/201x/2012/01/17/HttpURLConnection


1

HTTPURLConnection किस बिंदु पर दिए गए URL से संबंध स्थापित करने का प्रयास करता है?

URL में नामित पोर्ट पर यदि कोई हो, अन्यथा HTTP के लिए 80 और HTTPS के लिए 443। मेरा मानना ​​है कि यह प्रलेखित है।

मुझे किस बिंदु पर पता चल सकता है कि मैं सफलतापूर्वक कनेक्शन स्थापित करने में सक्षम था?

जब आप एक अपवाद प्राप्त किए बिना getInputStream () या getOutputStream () या getResponseCode () कॉल करते हैं।

क्या एक कनेक्शन स्थापित कर रहे हैं और एक चरण / विधि कॉल में किए गए वास्तविक अनुरोध भेज रहे हैं? क्या विधि है?

नहीं और कोई नहीं।

क्या आप गेटमैन के कार्यकाल में getOutputStream और getInputStream का कार्य समझा सकते हैं?

या तो पहले आवश्यक हो तो जोड़ता है, फिर आवश्यक स्ट्रीम लौटाता है।

मुझे लगता है कि जब सर्वर मैं कनेक्ट करने की कोशिश कर रहा हूँ नीचे है, मैं getOutputStream में एक अपवाद मिलता है। क्या इसका मतलब है कि HTTPURLConnection केवल एक कनेक्शन स्थापित करने के लिए शुरू होगा जब मैं getOutputStream आह्वान करता हूं? कैसे GetInputStream के बारे में? चूंकि मैं केवल getInputStream पर प्रतिक्रिया प्राप्त करने में सक्षम हूं, तो इसका मतलब यह है कि मैंने अभी तक getOutputStream पर कोई अनुरोध नहीं भेजा है, लेकिन बस एक कनेक्शन स्थापित करता है? जब मैं getInputStream आह्वान करता हूं तो क्या HttpURLConnection प्रतिक्रिया के लिए अनुरोध करने के लिए सर्वर पर वापस जाता है?

ऊपर देखो।

क्या मैं यह कहना सही हूं कि ओपनकॉन्नेशन केवल एक नया कनेक्शन ऑब्जेक्ट बनाता है लेकिन अभी तक कोई कनेक्शन स्थापित नहीं करता है?

हाँ।

मैं रीड ओवरहेड को कैसे माप सकता हूं और ओवरहेड को कनेक्ट कर सकता हूं?

कनेक्ट: get getoutInoutStream () या getOutputStream () जो भी आप पहले कॉल करते हैं, वापस करने के लिए लेता है। पढ़ें: EOS प्राप्त करने के लिए पहले पढ़ना शुरू करने से समय


1
मुझे लगता है कि ओपी का मतलब था कि किस बिंदु पर संबंध स्थापित किया गया है और किस बिंदु पर हम कनेक्शन की स्थिति जान सकते हैं। पोर्ट url से कनेक्ट नहीं होता है। मैं यह अनुमान लगा रहा हूं कि यह ओपनकनेक्ट () और getInoutStream () / getOutputStream () / getResponseCode () का उत्तर था जिसका उत्तर बाद में दिया गया।
अनिकेत ठाकुर

1

HTTPURLConnection किस बिंदु पर दिए गए URL से संबंध स्थापित करने का प्रयास करता है?

यह स्पष्ट करने योग्य है, 'उरलकोनेक्शन' उदाहरण है और फिर इसमें अंतर्निहित Tcp / Ip / SSL सॉकेट कनेक्शन , 2 अलग-अलग अवधारणाएँ हैं। 'UrlConnection' या 'HttpUrlConnection' उदाहरण एकल HTTP पेज अनुरोध का पर्याय है, और जब आप url.openConnection () कहते हैं, तो इसे बनाया जाता है। लेकिन अगर आप एक 'url' उदाहरण से कई url.openConnection () करते हैं तो यदि आप भाग्यशाली हैं, तो वे उसी Tcp / Ip सॉकेट और SSL हैंडशेकिंग सामान का पुनः उपयोग करेंगे ... यदि आप अच्छे हैं एक ही सर्वर के लिए बहुत सारे पेज अनुरोध करना, विशेष रूप से अच्छा है यदि आप एसएसएल का उपयोग कर रहे हैं जहां सॉकेट स्थापित करने का ओवरहेड बहुत अधिक है।

देखें: HttpURLConnection कार्यान्वयन


0

मैं निम्न स्तर के पैकेट एक्सचेंज पर कब्जा करने के लिए अभ्यास से गुजरा, और पाया कि नेटवर्क कनेक्शन केवल getInputStream, getOutputStream, getResponseCode, getResponseMessage आदि जैसे ऑपरेशन्स से चालू होता है।

जब मैं ड्रॉपबॉक्स पर फाइल अपलोड करने के लिए एक छोटा सा प्रोग्राम लिखने की कोशिश करता हूं तो यहां पैकेट एक्सचेंज पर कब्जा कर लिया जाता है।

यहां छवि विवरण दर्ज करें

नीचे मेरा खिलौना कार्यक्रम और एनोटेशन है

    /* Create a connection LOCAL object,
     * the openConnection() function DOES NOT initiate
     * any packet exchange with the remote server.
     * 
     * The configurations only setup the LOCAL
     * connection object properties.
     */
    HttpURLConnection connection = (HttpURLConnection) dst.openConnection();
    connection.setDoOutput(true);
    connection.setRequestMethod("POST");
    ...//headers setup
    byte[] testContent = {0x32, 0x32};

    /**
     * This triggers packet exchange with the remote
     * server to create a link. But writing/flushing
     * to a output stream does not send out any data.
     * 
     * Payload are buffered locally.
     */
    try (BufferedOutputStream outputStream = new BufferedOutputStream(connection.getOutputStream())) {
        outputStream.write(testContent);
        outputStream.flush();
    }

    /**
     * Trigger payload sending to the server.
     * Client get ALL responses (including response code,
     * message, and content payload) 
     */
    int responseCode = connection.getResponseCode();
    System.out.println(responseCode);

    /* Here no further exchange happens with remote server, since
     * the input stream content has already been buffered
     * in previous step
     */
    try (InputStream is = connection.getInputStream()) {
        Scanner scanner = new Scanner(is);
        StringBuilder stringBuilder = new StringBuilder();
        while (scanner.hasNextLine()) {
        stringBuilder.append(scanner.nextLine()).append(System.lineSeparator());
        }
    }

    /**
     * Trigger the disconnection from the server.
     */
    String responsemsg = connection.getResponseMessage();
    System.out.println(responsemsg);
    connection.disconnect();
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.