前网络上最流行的协议就是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。

转载于:https://blog.51cto.com/leonpard/1172632

解析HttpURLConnection与代理服务器相关推荐

  1. Linux下的squid代理服务器——正向代理、反向代理(cdn加速)

    一.squid代理服务器概述及功能 1. 什么是squid代理服务器? Squid是一个高性能的代理缓存服务器,Squid支持FTP.gopher.HTTPS和HTTP协议. 和一般的代理缓存软件不同 ...

  2. NGINX工作原理解析

    1 反向代理 1.1 概念 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给intern ...

  3. socks代理服务器协议的说明

    转自:http://gc063tzf.blog.163.com/blog/static/11216292201210246448371/(侵删) socks代理里面,有socks4 socks4a s ...

  4. Nginx的核心原理解析

    Nginx 反向代理VS正向代理: 反向代理服务器对于客户端而言它就像是原始服务器,并且客户端不需要进行任何特别的设置.客户端向反向代理的命名空间(name-space)中的内容发送普通请求,接着反向 ...

  5. 反向代理服务器(转)

    反向代理及Nginx示例 1 反向代理的概念 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果 ...

  6. 2020网易前端校招面试题解析

    前面的话 题目都是选自牛客. 解析 (1) 跨域请求中,需要设置哪个属性为true,才能携带cookie信息? 解析:跨域请求要想带上cookie,必须将withCredential属性设置为true ...

  7. Linux下DNS轮询与Squid反向代理结合

    一.安装反向代理服务器 1.下载反向代理服务器软件采用squid,下载地址: http://www.squid-cache.org/Versions/v2/2.2/squid-2.2.STABLE5- ...

  8. nginx反向代理原理简介

    From:http://zcnick.blog.51cto.com/1992444/774662 1.反向代理的概念 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上 ...

  9. 如何优化网站的响应时间

    Web应用中访问数据库的开销比较大,要提高Web应用的性能就要避免过多地访问数据库.尽管频繁地访问数据库会降低应用性能,但是,有时大量的数据库访问依然在所难免,原因在于: 虽然使用缓存(如Memcac ...

最新文章

  1. ffmpeg 常用命令
  2. 潘建伟团队首次实现18个光量子比特纠缠,刷新世界记录
  3. 在线旅游的2020:洗牌重组、直播自救、跨界面敌
  4. OS--进程间通信详解(二)
  5. 改变libreOffice的Calc的背景颜色
  6. java 时间段内月份_java获取某段时间内的月份列表
  7. zookeeper 应用开发
  8. python 硬件模拟_如何编写一个硬件模拟器?
  9. [转]FreeTextBox使用详解
  10. 条件变量的陷阱,惊群效应(转载)
  11. [转]NetBeans开发Applet方法实例学习
  12. RTX 2080 Ti 刚捂热,卡皇3080Ti 就要来了?
  13. Uncaught TypeError:Cannot read property 'call' of underfined
  14. 基于JAVA-超市会员积分管理系统-计算机毕业设计源码+系统+lw文档+部署
  15. Linux面试最高频的5个基本问题
  16. 获取当前所在地的天气
  17. (二)Spring自动装配
  18. Apollo学习笔记(15)Mini-Snap
  19. MacBook pro 用什么vpn 好_扫地机器人真得好用么?云米互联网扫地机Pro测评!
  20. 每日一思(2022.5.6)——非理性行为

热门文章

  1. 匿名对象,String类
  2. 你可能不知道的字符比较中的“秘密”
  3. 初次远程做Linux Iptables规则注意事项
  4. ZH奶酪:编程语言入门经典100例【Python版】
  5. shiro web环境初始化过程
  6. ubuntu16.04打造vim和python3的IDE
  7. JSONObject跟JSONArray来自不同的包会有不同的功能
  8. JavaScript中对象深复制
  9. php处理管道文件流
  10. js如何保证iframe里的内容,显示在父窗口