天空是藍色的

          做好軟件為中國 #gcc -c helloworld.c -o helloworld.o //編譯目標文件 #gcc helloworld.o -o helloworld //編譯成可執行exe #helloworld //運行exe
          數據加載中……
          代碼中通過代理訪問外部資源(轉貼)
          http://spaces.msn.com/members/savagardn/Blog/cns!1pzu-0W6-WxMGeUbOUArh6Eg!105.entry

          目前網絡上最流行的協議就是HTTP協議。HTTP協議有許多優點,例如它能夠穿越防火墻。同時HTTP也是很多其他協議的基礎,例如SOAP協議就是建立在HTTP協議之上的。

          Java通過兩種API對HTTP提供支持,一種是servlet API,它覆蓋了服務器端的編程問題;另一種是java.net包,它通過HttpURLConnection類在客戶端提供了對HTTP協議的支持。但是我在使用servlet API的時候曾經遇到過一些問題。本文將介紹我曾遇到過的一些問題和相應的解決辦法。

          基礎知識

          通常在企業網絡中,一個終端通過代理服務器同互聯網連接起來,代理服務器負責監視網絡流量和執行安全規則。在java.net API中,軟件可以通過兩個屬性來支持代理服務器,它們分別是http.proxyHost和http.proxyPort。它們必須被設定為相應的代理服務器和端口,下面的代碼展示了如何設定這兩個屬性:

          String url = "http://www.digitalcq.com/",
             proxy = "proxy.digitalcq.com",
             port = "8080";
          URL server = new URL(url);
          Properties systemProperties = System.getProperties();
          systemProperties.setProperty("http.proxyHost",proxy);
          systemProperties.setProperty("http.proxyPort",port);
          HttpURLConnection connection = (
              HttpURLConnection)server.openConnection();
          connection.connect();
          InputStream in = connection.getInputStream();
          readResponse(in);


          在上面的程序中,你需要根據實際情況設定代理服務器和端口。如果你不知道該如何設置的話,可以詢問你們公司的網絡管理員。

          使用驗證

          通常公司會要求員工在連接到互聯網之前登錄到代理服務器。通過登錄這種機制使公司可以更好的監控員工對互聯網的使用,例如監控員工都訪問了哪些網站。HttpURLConnection通過驗證類支持代理服務器驗證。下面是一個如何利用HttpURLConnection類進行驗證的例子。首先需要實現一個驗證者:

          public class SimpleAuthenticator
             extends Authenticator
          {
             private String username,
                            password;
              public SimpleAuthenticator(String username,String password)
             {
                this.username = username;
                this.password = password;
             }
              protected PasswordAuthentication getPasswordAuthentication()
             {
                return new PasswordAuthentication(
                       username,password.toCharArray());
             }
          }


          然后,通過Authenticator.setDefault()方法注冊驗證者:

          String url = "http://www.digitalcq.com/",
                 proxy = "proxy.digitalcq.com",
                 port = "8080",
                 username = "usr",
                 password = "pwd";
          Authenticator.setDefault(new SimpleAuthenticator(
                 username,password));
          URL server = new URL(url);
          Properties systemProperties = System.getProperties();
          systemProperties.setProperty("http.proxyHost",proxy);
          systemProperties.setProperty("http.proxyPort",port);
          HttpURLConnection connection = (
              HttpURLConnection)server.openConnection();
          connection.connect();
          InputStream in = connection.getInputStream();
          readResponse(in);


          問題

          上面介紹的都是HttpURLConnection類能夠正常工作的情況。但是我在實際情況中遇到了一些網絡,在這些網絡中,HttpURLConnection類無法正常工作。最后我發現關鍵的問題在于使用了不正確的DNS配置。在實際情況中,HttpURLConnection類總是先嘗試利用DNS服務器來解析地址名稱。通常情況下,這種嘗試會失敗,而代理服務器會將連接重新定向。但是某些DNS服務器會返回一些不正確的響應,從而導致程序拋出UnknownHostException異常。作為一個程序員,系統不會為了你的程序更改DNS服務器的配置,因此你需要找出解決這個問題的方法。我的方案是通過自己實現HTTP協議來解決這個問題。例如一個GET命令可以用下面的代碼來實現:

          String url = "http://www.digitalcq.com/",
                 proxy = "proxy.digitalcq.com",
                 port = "8080",
                 authentication = "usr:pwd";
          URL server = new URL(url);
          Socket socket = new Socket(proxy,port);
          Writer writer = new OutputStreamWriter(socket.getOutputStream(),
                                                 "US-ASCII");
          writer.write("GET " + server.toExternalForm() + " HTTP/1.0\r\n");
          writer.write("Host: " + server.getHost() + "\r\n");
          writer.write("Proxy-Authorization: Basic "
                       + new sun.misc.BASE64Encoder().encode(
                         authentication.getBytes())
                       + "\r\n\r\n");
          writer.flush();
          BufferedReader reader = new BufferedReader(new InputStreamReader(
                                      socket.getInputStream(),"US-ASCII"));
          String line = reader.readLine();
          if(line != null && line.startsWith("HTTP/"))
          {
             int sp = line.indexOf(' ');
             String status = line.substring(sp + 1,sp + 4);
             if(status.equals("200"))
             {
                while(line.length() != 0)
                   line = reader.readLine();
                readResponse(reader);
             }
             else
                throw new FileNotFoundException("Host reports error " +
                                                 status);
          }
          else
             throw new IOException("Bad protocol");
          reader.close();
          writer.close();
          socket.close();


          在上面的代碼中,大家可以注意到代理服務器的用戶名和密碼的格式是:

          username:password,

          并且程序對它們基于Base 64進行了編碼。如果需要參考HTTP協議,可以到http://www.ietf.org/rfc/rfc2616.txt

          posted on 2005-11-07 15:44 bluesky 閱讀(498) 評論(0)  編輯  收藏 所屬分類: 基礎知識

          主站蜘蛛池模板: 巴青县| 随州市| 彭州市| 镇安县| 基隆市| 上林县| 泸溪县| 久治县| 陈巴尔虎旗| 桂平市| 开江县| 称多县| 乌苏市| 康保县| 新乐市| 台南县| 江安县| 南溪县| 常熟市| 苏尼特右旗| 武穴市| 建始县| 股票| 保山市| 濮阳市| 耒阳市| 五大连池市| 顺昌县| 四子王旗| 中卫市| 安达市| 防城港市| 大庆市| 潞西市| 呼伦贝尔市| 荣成市| 西昌市| 渭南市| 中阳县| 本溪市| 扎鲁特旗|