用户名:

密码:

验证码:

2014年
当前位置:首页 > 生活百科 > 网友说说 >

通过Socket实现Http中Get请求

2016-12-01 11:04 合德网 点击次数 :

对于网络通信这部分,一直搞不清楚网络模型中传输层协议和应用层协议是怎么进行交互的,于是想通过直接使用TCP协议实现http请求的发送,所以这里通过Socket编程来完成这项工作,在Java中还可以使用原生的HttpURLConnection或者Apache中的HttpClient完成Http请求的发送,但是这种方式已经是对Socket进行封装,对我们理解Http的原理没有帮助。

要想完成这个功能需要以下两部分技能:

Java网络编程的相关内容 Http协议的相关内容:不要求特别了解,但是基本的机制需要知道

首先把整体的代码先列出来,如下MyHttpGet:

public class MyHttpGet { private String host; private int port; private String contextPath; private StringBuffer requestMessage; private Map<String, String> headers = new LinkedHashMap<>(); private Map<String, String> params = new HashMap<>(); public MyHttpGet(String address) throws MalformedURLException{ URL url = new URL(address); this.port = url.getDefaultPort(); this.host = url.getHost(); this.contextPath = url.getPath(); headers.put("Host", this.host); } public InputStream execute() throws IOException { StringBuffer requestMessage = new StringBuffer(); List<String> pairs = new ArrayList<>(); // 处理查询参数 params.keySet().stream().forEach(key->{ StringBuffer pair = new StringBuffer(); pair.append(key); pair.append("="); pair.append(params.get(key)); pairs.add(pair.toString()); }); if(params.size() > 0){ this.contextPath = this.contextPath + "?" + String.join("&", (String[])pairs.toArray()); } // http 协议内容 requestMessage.append("GET " + this.contextPath + " HTTP/1.1" + System.getProperty("line.separator")); for(String key: headers.keySet()){ requestMessage.append(key); requestMessage.append(": "); requestMessage.append(headers.get(key)); requestMessage.append(System.getProperty("line.separator")); } requestMessage.append("\r\n"); Socket socket = new Socket(); SocketAddress socketAddress = new InetSocketAddress(this.host, this.port); socket.connect(socketAddress); BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); System.out.println(requestMessage.toString()); bufferedWriter.write(requestMessage.toString()); bufferedWriter.flush(); return socket.getInputStream(); } public MyHttpGet addParam(String key, String value){ params.put(key, value); return this; } public MyHttpGet addHeader(String key, String value){ headers.put(key, value); return this; } }

从上面的代码看,其实所谓的发送Http请求就是通过建立TCP连接,然后通过该连接的通道将格式化的数据传输过去,这种格式化的数据遵从一定的规则,这个规则就是Http协议。

但是在实现的过程中需要注意的几点如下:

关于Http的协议的基本格式:
在Http的每个请求头字段结束后需要换行,如果没有该标志或者该标志写错了,则会返回400 Bad Request错误在windows中使用\r\n,这里使用的是System.getProperty("line.separator")可以做到与平台无关; 在所有的请求头字段结束后需要在结尾添加一个空行标识请求头已经结束,可以开始添加数据了,这个在Get方法中不太明显,但是在Post方法中却一目了然,如果没有该标志则服务器不会返回数据的,因为无法解析; 关于Http请求头字段的顺序,在RFC文档中说明它们之间的顺序是不重要的,但是一般都是把在请求和响应中都能用的字段放在最前面,然后才是只在请求和响应中使用的字段,但是http请求headers的顺序中说明顺序还是起作用的,我认为既然官方规范没有说明顺序对请求和响应有影响,可能是具体技术实现者自己做的限制; 关于对返回的数据进行解码的问题,自己实现的Http客户端肯定会遇到乱码的问题,如果想要解决这部分问题,也需要了解服务端的编码是怎样的; 在使用Java的网络API去编程的时候,会发现如果响应不返回,客户端就一直阻塞,这样会导致整个程序运行变慢,因为这套API使用的IO模型是同步阻塞模型;

对我们的Http客户端进行测试如下:

MyHttpGet myHttpGet = new MyHttpGet("http://blog.csdn.net/lmy86263"); myHttpGet.addHeader("Connection", "keep-alive") .addHeader("Cache-Control", "max-age=0") .addHeader("Upgrade-Insecure-Requests", "1") .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36") .addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8") .addHeader("Accept-Encoding", "gzip, deflate, sdch") .addHeader("Accept-Language", "en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4"); InputStream inputStream = null; try { inputStream = myHttpGet.execute(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String line; while((line = bufferedReader.readLine()) != null){ System.out.print(line + "\r\n"); } inputStream.close(); } catch (IOException e) { e.printStackTrace(); }

返回结果如下:

通过Socket实现Http中Get请求

这个客户端只是一个非常简陋的例子,相对成熟的客户端还差得很远,比如性能效率、错误处理、超时重试、缓存以及认证等相关问题,但是通过这个例子发现其实其中的原理并不复杂,有助于我们对相关技术进行理解。

相关文章:

Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing

Java中写入文件时换行符是用“\r\n"还是"\n”?

以上就是通过Socket实现Http中Get请求的全文介绍,希望对您学习和使用java程序开发有所帮助.

这些内容可能对你也有帮助

更多Java编程可查看Java编程列表页。

(责任编辑:管理员)
文章人气:
(请您在发表言论时自觉遵守互联网相关政策法律法规,文明上网,健康言论。)
用户名:
验证码:
首页 | 新闻 | 财经 | 军事 | 百科 | 科技 | 数码 | 汽车 | 游戏 | 娱乐 | 体育 | 文化 | 教育 | 房产 | 旅游 | 健康 | 女性 | 明星 | 美女