首页 > 技术文章 > Socket 模拟HTTP客户端请求

hehongtao 2016-03-14 17:16 原文

 

 1 import java.io.IOException;
 2 import java.io.InputStream;
 3 import java.io.OutputStreamWriter;
 4 import java.net.InetAddress;
 5 import java.net.Socket;
 6 import java.net.UnknownHostException;
 7 import java.util.ArrayList;
 8 
 9 /**
10  * 一个简单的HTTP客户端,发送HTTP请求,模拟浏览器 可打印服务器发送过来的HTTP消息
11  */
12 public class HttpClient {
13     private static String encoding = "UTF-8";
14 
15     public static void main(String[] args) {
16         try {
17             Socket s = new Socket(InetAddress.getLocalHost(), 8080);
18             OutputStreamWriter osw = new OutputStreamWriter(s.getOutputStream());
19             StringBuffer sb = new StringBuffer();
20             sb.append("GET /slsint_gd/reportview/reportViewList.jsp HTTP/1.1\r\n");
21             sb.append("Host: localhost:8088\r\n");
22             sb.append("Connection: Keep-Alive\r\n");
23             // 注,这是关键的关键,忘了这里让我搞了半个小时。这里一定要一个回车换行,表示消息头完,不然服务器会等待
24             sb.append("\r\n");
25             osw.write(sb.toString());
26             osw.flush();
27 
28             // --输出服务器传回的消息的头信息
29             InputStream is = s.getInputStream();
30             String line = null;
31             int contentLength = 0;// 服务器发送回来的消息长度
32             // 读取所有服务器发送过来的请求参数头部信息
33             do {
34                 line = readLine(is, 0);
35                 // 如果有Content-Length消息头时取出
36                 if (line.startsWith("Content-Length")) {
37                     contentLength = Integer.parseInt(line.split(":")[1].trim());
38                 }
39                 // 打印请求部信息
40                 System.out.print(line);
41                 // 如果遇到了一个单独的回车换行,则表示请求头结束
42             } while (!line.equals("\r\n"));
43 
44             // --输消息的体
45             System.out.print(readLine(is, contentLength));
46 
47             // 关闭流
48             is.close();
49 
50         } catch (UnknownHostException e) {
51             e.printStackTrace();
52         } catch (IOException e) {
53             e.printStackTrace();
54         }
55     }
56 
57     /*
58      * 这里我们自己模拟读取一行,因为如果使用API中的BufferedReader时,它是读取到一个回车换行后
59      * 才返回,否则如果没有读取,则一直阻塞,直接服务器超时自动关闭为止,如果此时还使用BufferedReader
60      * 来读时,因为读到最后一行时,最后一行后不会有回车换行符,所以就会等待。如果使用服务器发送回来的
61      * 消息头里的Content-Length来截取消息体,这样就不会阻塞
62      * 
63      * contentLe 参数 如果为0时,表示读头,读时我们还是一行一行的返回;如果不为0,表示读消息体,
64      * 时我们根据消息体的长度来读完消息体后,客户端自动关闭流,这样不用先到服务器超时来关闭。
65      */
66     private static String readLine(InputStream is, int contentLe) throws IOException {
67         ArrayList lineByteList = new ArrayList();
68         byte readByte;
69         int total = 0;
70         if (contentLe != 0) {
71             do {
72                 readByte = (byte) is.read();
73                 lineByteList.add(Byte.valueOf(readByte));
74                 total++;
75             } while (total < contentLe);// 消息体读还未读完
76         } else {
77             do {
78                 readByte = (byte) is.read();
79                 lineByteList.add(Byte.valueOf(readByte));
80             } while (readByte != 10);
81         }
82 
83         byte[] tmpByteArr = new byte[lineByteList.size()];
84         for (int i = 0; i < lineByteList.size(); i++) {
85             tmpByteArr[i] = ((Byte) lineByteList.get(i)).byteValue();
86         }
87         lineByteList.clear();
88 
89         return new String(tmpByteArr, encoding);
90     }
91 }

 

HTTP/1.1 200 OK

Server: Apache-Coyote/1.1

Set-Cookie: JSESSIONID=1F27447B2CDF30A69009A219932E259D; Path=/slsint_gd/; HttpOnly

Content-Type: text/html;charset=utf-8

Content-Language: zh-CN

Content-Length: 1881

Date: Mon, 14 Mar 2016 09:11:44 GMT

 

 

 

<html>     <head>         <title>广州农商行外汇数据报送系统</title>         <link rel="stylesheet" type="text/css" media="all" href="/slsint_gd/styles/default.css;jsessionid=1F27447B2CDF30A69009A219932E259D" />         <script type="text/javascript" src="/slsint_gd/scripts/global.js;jsessionid=1F27447B2CDF30A69009A219932E259D"></script>     </head>  <body>   <center>      <div align="center" style=" width:99%">    <div align="left"><span class="pagebanner">共0项</span></div><div align="right"><span class="pagelinks"></span></div> <table id="reports" width="100%" cellpadding="0" class="reportViewList list" cellspacing="0"> <thead> <tr> <th width="20%" class="sortable"></th> <th width="20%" class="sortable"> <a href="http://localhost:8088/slsint_gd/reportview/;jsessionid=1F27447B2CDF30A69009A219932E259D?d-1341553-o=2&amp;d-1341553-s=1">报表名称</a></th> <th width="20%" class="sortable"> <a href="http://localhost:8088/slsint_gd/reportview/;jsessionid=1F27447B2CDF30A69009A219932E259D?d-1341553-o=2&amp;d-1341553-s=2">报表类型</a></th> <th width="20%" class="sortable"> <a href="http://localhost:8088/slsint_gd/reportview/;jsessionid=1F27447B2CDF30A69009A219932E259D?d-1341553-o=2&amp;d-1341553-s=3">机构名称</a></th> <th width="10%" class="sortable"> <a href="http://localhost:8088/slsint_gd/reportview/;jsessionid=1F27447B2CDF30A69009A219932E259D?d-1341553-o=2&amp;d-1341553-s=4">报表日期</a></th> <th width="2%">操作</th></tr></thead> <tbody><tr class="empty"><td colspan="6">没有列表项</td></tr></tbody></table><div align="left"><span class="pagebanner">共0项</span></div><div align="right"><span class="pagelinks"></span></div>     <script type="text/javascript">      <!--       highlightTableRows("reports");      //-->     </script>      </div>      </center> </body> </html>

推荐阅读