哇,一看标题怎么这么长啊,其实意思很简单,哥讨厌用HTTP Client做POST与GET提交觉得那个毕竟是别人写得API库,所以我就自己实现了一个简单的HTTP客户端,支持POST方式提交数据,GET方式查询数据,是测试Restful API比较方便点,然后支持form与JSON两种方式提交数据,当然也支持返回数据为JSON格式.当然这些东西都是基于JAVA Socket直接完成的,不借助任何第三方的库,主要是JDK的API其实已经够用啦. 当然我也没有用URLConnect这个东西,毕竟它在Socket基础上又包装了一下,有违我写这篇文章的目的.
好啦,讲完理由,下面就说说要怎么样才能实现啊,光说不练假把式啊!大致分了几个步骤
一:当然是要知道HTTP协议,知道常用的HTTP请求头,比如Host, Accept, Content-Type 知道HTTP协议支持的方法,常用有GET/POST/PUT/DELETE等如果不知道,也不用担心,我保证你读完这篇文章,你就知道一些啦,当然有个最好的参考文档就是HTTP相关的RFC文档,认真读一下肯定解决你自己心中的HTTP那些疑惑
二: 知道发送HTTP GET与POST格式很重要, 固定的格式如下:
[REQUEST]<SP><URL><SP>[HTTP VERSION]<CLRF>
[REQUEST HEADER: ]<SP>[VALUE]<CLRF>
可以有多个请求头
最后<CLRF>
发送完HTTP请求头部以后, 针对不同请求如POST要发送内容部分,发送完成以后同样,以<CLRF>结尾.
解释: <SP>表示空格, <CLRF>表示回车换行JAVA中表示为”\r\n”REQUEST表示HTTP请求命令,可以为POST, GET, PUT, DELETE等之一,HTTP VERSION的常见可能值为HTTP/1.1或者HTTP/1.0
三: 如果1与2的知识你都具备了,下面就来介绍一下JAVA Socket的相关知识,如何创建一个JAVA客户端套接字Socket s = new Socket()如此即可,简单吧!如何连接到远程的主机与端口, 当提供URL字符串时候,可以这么做
1 2 3 4 5 6 7 8 9 |
URL url = new URL(“http://blog.csdn.net/jia20003”); String host = url.getHost; int port = url.getDefaultPort(); SocketAddress dest = new InetSocketAddress(this.host, this.port); s.connect(dest); |
即可连接到远程主机,下面就可以请求文章内容了, 也很容易的
1 2 3 4 5 6 7 8 9 |
String path = "/jia20003/article/details/16908661"; SocketAddress dest = new InetSocketAddress(this.host, this.port); socket.connect(dest); OutputStreamWriter streamWriter = new OutputStreamWriter(socket.getOutputStream()); bufferedWriter = new BufferedWriter(streamWriter); bufferedWriter.write("GET " + path + " HTTP/1.1\r\n"); bufferedWriter.write("Host: " + this.host + "\r\n"); bufferedWriter.write("\r\n"); bufferedWriter.flush(); |
最后也是最重要的一点,字符编码,尽量都用同一种字符编码来发 送请求数据,推荐使用utf-8测试程序, 我写两个简单的PHP文件放 在wamp server上,完成对全部代码的测试。
四:关于HTTP与HTTPS
HTTP协议是位于第四层协议TCP之上完成的应用层协议, 端到端都是明文传送,别人一旦网络抓包以后都可以看到你的提交与请求数据,这个好像不太安全. HTTP协议的默认端口是80这个是RFC文档声明的,属于官方标准,没什么道理可以讲.HTTPS是基于SSL加密传输的,这样别人截获你的数据包破解的概率要小一点,比HTTP安全一点,其默认端口是443, 好像QQ邮箱与谷歌的WEB Mail邮箱都是基于HTTPS. 但是HTTPS通信方式只是传输数据加密,都客户端来说是透明的,它还是一样要遵守HTTP协议规范来发送POST与GET请求等.完整的测试程序如下:
http协议实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
package com.gloomyfish.http.client; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; import java.net.URLEncoder; public class TestDemo { private int port; private String host; private Socket socket; private BufferedReader bufferedReader; private BufferedWriter bufferedWriter; public TestDemo(String host, int port) { socket = new Socket(); this.host = host; this.port = port; } public void sendGet() throws IOException { String path = "/zhigang/getDemo.php"; SocketAddress dest = new InetSocketAddress(this.host, this.port); socket.connect(dest); OutputStreamWriter streamWriter = new OutputStreamWriter(socket.getOutputStream()); bufferedWriter = new BufferedWriter(streamWriter); bufferedWriter.write("GET " + path + " HTTP/1.1\r\n"); bufferedWriter.write("Host: " + this.host + "\r\n"); bufferedWriter.write("\r\n"); bufferedWriter.flush(); BufferedInputStream streamReader = new BufferedInputStream(socket.getInputStream()); bufferedReader = new BufferedReader(new InputStreamReader(streamReader, "utf-8")); String line = null; while((line = bufferedReader.readLine())!= null) { System.out.println(line); } bufferedReader.close(); bufferedWriter.close(); socket.close(); } public void sendPost() throws IOException { String path = "/zhigang/postDemo.php"; String data = URLEncoder.encode("name", "utf-8") + "=" + URLEncoder.encode("gloomyfish", "utf-8") + "&" + URLEncoder.encode("age", "utf-8") + "=" + URLEncoder.encode("32", "utf-8"); // String data = "name=zhigang_jia"; SocketAddress dest = new InetSocketAddress(this.host, this.port); socket.connect(dest); OutputStreamWriter streamWriter = new OutputStreamWriter(socket.getOutputStream(), "utf-8"); bufferedWriter = new BufferedWriter(streamWriter); bufferedWriter.write("POST " + path + " HTTP/1.1\r\n"); bufferedWriter.write("Host: " + this.host + "\r\n"); bufferedWriter.write("Content-Length: " + data.length() + "\r\n"); bufferedWriter.write("Content-Type: application/x-www-form-urlencoded\r\n"); bufferedWriter.write("\r\n"); bufferedWriter.write(data); bufferedWriter.write("\r\n"); bufferedWriter.flush(); BufferedInputStream streamReader = new BufferedInputStream(socket.getInputStream()); bufferedReader = new BufferedReader(new InputStreamReader(streamReader, "utf-8")); String line = null; while((line = bufferedReader.readLine())!= null) { System.out.println(line); } bufferedReader.close(); bufferedWriter.close(); socket.close(); } public static void main(String[] args) { TestDemo td = new TestDemo("127.0.0.1",8099); try { // td.sendGet(); //send HTTP GET Request td.sendPost(); // send HTTP POST Request } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } |
想要成为支持HTTPS客户端, 只要在创建Socket的时候如下:
1 |
socket = (SSLSocket)((SSLSocketFactory)SSLSocketFactory.getDefault()).createSocket(this.host, port); |
https协议实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
package zmx.socket.http; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.Socket; import java.net.URLEncoder; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; public class SocketForHttpTest { private int port; private String host; private Socket socket; private BufferedReader bufferedReader; private BufferedWriter bufferedWriter; public SocketForHttpTest(String host,int port) throws Exception { this.host = host; this.port = port; /** * http协议 */ //socket = new Socket(this.host, this.port); /** * https协议 */ socket = (SSLSocket)((SSLSocketFactory)SSLSocketFactory.getDefault()).createSocket(this.host, this.port); } public void sendGet() throws IOException { //String requestUrlPath = "/z69183787/article/details/17580325"; String requestUrlPath = "/"; OutputStreamWriter streamWriter = new OutputStreamWriter(socket.getOutputStream()); bufferedWriter = new BufferedWriter(streamWriter); bufferedWriter.write("GET " + requestUrlPath + " HTTP/1.1\r\n"); bufferedWriter.write("Host: " + this.host + "\r\n"); bufferedWriter.write("\r\n"); bufferedWriter.flush(); BufferedInputStream streamReader = new BufferedInputStream(socket.getInputStream()); bufferedReader = new BufferedReader(new InputStreamReader(streamReader, "utf-8")); String line = null; while((line = bufferedReader.readLine())!= null){ System.out.println(line); } bufferedReader.close(); bufferedWriter.close(); socket.close(); } public void sendPost() throws IOException { String path = "/"; String data = URLEncoder.encode("name", "utf-8") + "=" + URLEncoder.encode("张三", "utf-8") + "&" + URLEncoder.encode("age", "utf-8") + "=" + URLEncoder.encode("32", "utf-8"); // String data = "name=zhigang_jia"; System.out.println(">>>>>>>>>>>>>>>>>>>>>"+data); OutputStreamWriter streamWriter = new OutputStreamWriter(socket.getOutputStream(), "utf-8"); bufferedWriter = new BufferedWriter(streamWriter); bufferedWriter.write("POST " + path + " HTTP/1.1\r\n"); bufferedWriter.write("Host: " + this.host + "\r\n"); bufferedWriter.write("Content-Length: " + data.length() + "\r\n"); bufferedWriter.write("Content-Type: application/x-www-form-urlencoded\r\n"); bufferedWriter.write("\r\n"); bufferedWriter.write(data); bufferedWriter.write("\r\n"); bufferedWriter.flush(); BufferedInputStream streamReader = new BufferedInputStream(socket.getInputStream()); bufferedReader = new BufferedReader(new InputStreamReader(streamReader, "utf-8")); String line = null; while((line = bufferedReader.readLine())!= null) { System.out.println(line); } bufferedReader.close(); bufferedWriter.close(); socket.close(); } public static void main(String[] args) throws Exception { /** * http协议测试 */ //SocketForHttpTest forHttpTest = new SocketForHttpTest("www.baidu.com", 80); /** * https协议测试 */ SocketForHttpTest forHttpTest = new SocketForHttpTest("www.baidu.com", 443); try { //forHttpTest.sendGet(); forHttpTest.sendPost(); } catch (IOException e) { e.printStackTrace(); } } } |
所以有时候离开apache的HTTP Client等第三方Jar,程序员也是一样活!