今天再测试Socket编程时,无法连接外网。公司用的是Http的代理。上网搜索也没看太懂,所以花了大量时间来学习。看了HTTP和TCP协议的关系好,才有所明白。现在能通过Socket使用HTTP代理了,结果很简单,过程却好难。
1. 先简要说说HTTP和TCP(具体内容自行Google,资料很多很全),这里就讲讲要点:
HTTP:是应用层协议,是基于传输层协议的。
TCP: 是传输层协议,是基于网络层协议的。
IP: 是网络层协议。
一个TCP的连接要进行三次握手(就像转户口一样,不详说),HTTP只是一个应用协议,也就是相当于一个自定义协议,即其没有对底层的传输方式进行干涉,只是对数据内容格式进行了定义。打个比方,别人说“SB”(你的名字),你回答“是”,仅仅是内容格式,没有改变声音的传输方式(通过声波传送<网络硬件介质>,通过双方都能听懂的语言<TCP/IP>)。同理,FTP, Telnet也是一种应用层协议,打个比方对于FTP,别人说“SB",你回答“哎”,只是格式内容不同而已。
2. 认识到以上之后,我们再说说HTTP代理,从上可以理解,HTTP代理服务器就是这样一台机器:你把所有的HTTP请求(不管是想请求百度还是Google)都发到这个HTTP代理服务器,然后这个HTTP代理服务器请求你要访问的最终地址,把响应回传给你。这里还要注意它代理的是HTTP协议,而HTTP又是基于TCP的,也就是说这个服务器代理的是指定HTTP内容格式的TCP连接。再说下去也没意思了,看以下代码:
//以下地址是代理服务器的地址 Socket socket = new Socket("10.1.2.188", 80); //写与的内容就是遵循HTTP请求协议格式的内容,请求百度 socket.getOutputStream().write(new String("GET http://www.baidu.com/ HTTP/1.1\r\n\r\n").getBytes()); byte[] bs = new byte[1024]; InputStream is = socket.getInputStream(); int i; while ((i = is.read(bs)) > 0) { System.out.println(new String(bs, 0, i)); } is.close();
当然在Java中,有Proxy代理上网的使用,此时使用URL(HTTP)就不涉及Socket(TCP)了,看如下代码
//设置代理 System.setProperty("http.proxySet", "true"); System.setProperty("http.proxyHost", "10.1.2.188"); System.setProperty("http.proxyPort", "80"); //直接访问目的地址 URL url = new URL("http://www.baidu.com"); URLConnection con = url.openConnection(); InputStreamReader isr = new InputStreamReader(con.getInputStream()); char[] cs = new char[1024]; int i = 0; while ((i = isr.read(cs)) > 0) { System.out.println(new String(cs, 0, i)); } isr.close();
最后总结一下:
在使用HTTP代理的环境中,
如果使用Socket(TCP)连接外网,则直接连接代理服务器,然后在发送的HTTP请求中指明要转发到的外网网址。
如果使用URL(HTTP)连接外网,则需要设置HTTP代理参数或使用Proxy。
OK,明白以后可以随意使用了,看以下代码,使用NIO的Socket通过HTTP代理访问外网的例子:
SocketChannel sc = SocketChannel.open(new InetSocketAddress("10.1.2.188", 80)); sc.write(Charset.forName("utf8").encode("GET http://www.baidu.com/ HTTP/1.1\r\n\r\n")); ByteBuffer buffer = ByteBuffer.allocate(1024); while (sc.read(buffer) != -1) { buffer.flip(); System.out.println(Charset.forName("utf8").decode(buffer)); buffer.clear(); } sc.close();
Java Socket编程中加入代理示例
有些时候我们的网络不能直接连接到外网, 需要使用http或是https或是socket代理来连接到外网, 这里是java使用代理连接到外网的一些方法,:方法一使用系统属性来完成代理设置, 这种方法比较简单, 但是不能对单独的连接来设置代理:
public static void main(String[] args) { Properties prop = System.getProperties(); // 设置http访问要使用的代理服务器的地址 prop.setProperty("http.proxyHost", "192.168.0.254"); // 设置http访问要使用的代理服务器的端口 prop.setProperty("http.proxyPort", "8080"); // 设置不需要通过代理服务器访问的主机,可以使用*通配符,多个地址用|分隔 prop.setProperty("http.nonProxyHosts", "localhost|192.168.0.*"); // 设置安全访问使用的代理服务器地址与端口 // 它没有https.nonProxyHosts属性,它按照http.nonProxyHosts 中设置的规则访问 prop.setProperty("https.proxyHost", "192.168.0.254"); prop.setProperty("https.proxyPort", "443"); // 使用ftp代理服务器的主机、端口以及不需要使用ftp代理服务器的主机 prop.setProperty("ftp.proxyHost", "192.168.0.254"); prop.setProperty("ftp.proxyPort", "2121"); prop.setProperty("ftp.nonProxyHosts", "localhost|192.168.0.*"); // socks代理服务器的地址与端口 prop.setProperty("socksProxyHost", "192.168.0.254"); prop.setProperty("socksProxyPort", "8000"); // 设置登陆到代理服务器的用户名和密码 Authenticator.setDefault(new MyAuthenticator("userName", "Password")); } static class MyAuthenticator extends Authenticator { private String user = ""; private String password = ""; public MyAuthenticator(String user, String password) { this.user = user; this.password = password; } protected PasswordAuthentication getPasswordAuthentication() { returnnew PasswordAuthentication(user, password.toCharArray()); } }
public static void main(String[] args) { try { URL url = new URL("http://www.baidu.com"); // 创建代理服务器 InetSocketAddress addr = new InetSocketAddress("192.168.0.254", 8080); // Proxy proxy = new Proxy(Proxy.Type.SOCKS, addr); // Socket 代理 Proxy proxy = new Proxy(Proxy.Type.HTTP, addr); // http 代理 // 如果我们知道代理server的名字, 可以直接使用 // 结束 URLConnection conn = url.openConnection(proxy); InputStream in = conn.getInputStream(); // InputStream in = url.openStream(); String s = IOUtils.toString(in); System.out.println(s); } catch (Exception e) { e.printStackTrace(); } }
本文向大家介绍链表的原理及java实现代码示例,包括了链表的原理及java实现代码示例的使用技巧和注意事项,需要的朋友参考一下 一:单向链表基本介绍 链表是一种数据结构,和数组同级。比如,Java中我们使用的ArrayList,其实现原理是数组。而LinkedList的实现原理就是链表了。链表在进行循环遍历时效率不高,但是插入和删除时优势明显。下面对单向链表做一个介绍。 单链表的概念 链表是最基本
本文向大家介绍java代理实现爬取代理IP的示例,包括了java代理实现爬取代理IP的示例的使用技巧和注意事项,需要的朋友参考一下 仅仅使用了一个java文件,运行main方法即可,需要依赖的jar包是com.alibaba.fastjson(版本1.2.28)和Jsoup(版本1.10.2) 如果用了pom,那么就是以下两个: 完整的代码如下: 以上这篇java代理实现爬取代理IP的示例就是小编
本文向大家介绍Java SPI机制原理及代码实例,包括了Java SPI机制原理及代码实例的使用技巧和注意事项,需要的朋友参考一下 SPI的全名为:Service Provider Interface,大多数开发人员可能不熟悉,因为这个是针对厂商或者插件的。在java.util.ServiceLoader的文档里有比较详细的介绍。 简单的总结下 Java SPI 机制的思想。我们系统里抽象的各个模
本文向大家介绍Java 动态代理原理分析,包括了Java 动态代理原理分析的使用技巧和注意事项,需要的朋友参考一下 Java 动态代理原理分析 概要 AOP的拦截功能是由java中的动态代理来实现的。说白了,就是在目标类的基础上增加切面逻辑,生成增强的目标类(该切面逻辑或者在目标类函数执行之前,或者目标类函数执行之后,或者在目标类函数抛出异常时候执行。Spring中的动态代理是使用Cglib进行实
本文向大家介绍C++常见异常处理原理及代码示例解析,包括了C++常见异常处理原理及代码示例解析的使用技巧和注意事项,需要的朋友参考一下 编程中常见的错误 程序的编译错误——比较好解决,主要是一些语法错误 程序的运行错误——产生因素较为复杂,如空间不够,下标越界,访问非法空间等。 异常是指程序运行时出现的不正常,可分为一下几类: CPU异常;如在计算过程中,出现除数为0的情况。 内存异常,如: 使用
本文向大家介绍Java基础异常处理代码及原理解析,包括了Java基础异常处理代码及原理解析的使用技巧和注意事项,需要的朋友参考一下 这篇文章主要介绍了java基础异常处理代码及原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 异常的定义:中断了正常指令流的事件。 try..catch..finally结构: 输出结果: throw与thro