从我们在浏览器的地址栏输入http://blog.csdn.net/seu_calvin后回车,到我们看到该博客的主页,这中 间经历了什么呢?简单地回答这个问题,大概是经历了域名解析、 TCP的三次握手、建立TCP连接后发起
HTTP请求、服务器响应HTTP请求、浏览器解析html代码,同时请求html代码中的资源(如js、 css、图 片等)、最后浏览器对页面进行渲染并呈现给用户。下面分别介绍一下每个过程。
1.域名解析
以Chrome浏览器为例, Chrome会解析域名对应的IP地址。 (1) Chrome浏览器会首先搜索浏览器自身的DNS缓存(可以使用 chrome://net-internals/#dns 来进 行查看),浏览器自身的DNS缓存有效期比较短,且容纳有限,大概是1000条。如果自身的缓存中存在
blog.csdn.net 对应的IP地址并且没有过期,则解析成功。 (2)如果(1)中未找到,那么Chrome会搜索操作系统自身的DNS缓存(可以在命令行下使用 ipconfig /displaydns 查看)。如果找到且没有过期则成功。 (3)如果(2)中未找到,那么尝试读取位于C:\Windows\System32\drivers\etc下的hosts文件,如果 找到对应的IP地址则解析成功。 (4)如果(3)中未找到,浏览器首先会找TCP/IP参数中设置的本地DNS服务器,并请求LDNS服务器 来解析这个域名,这台服务器一般在你的城市的某个角落,距离你不会很远,并且这台服务器的性能都 很好,一般都会缓存域名解析结果,大约80%的域名解析到这里就完成了。否则本地DNS服务器会请求 根DNS服务器。 (5)本地DNS会把请求发至13台根DNS,根DNS服务器会返回所查询域的主域名服务器的地址(.net), 本地DNS服务器使用该IP信息联系负责.net域的这台服务器。这台负责.net域的服务器收到请求后,会返 回.net域的下一级DNS服务器地址(blog.csdn.net)给本地DNS服务器。以此类推,直至找到。
2.TCP的三次握手
这个部分正好之前整理过,可以参考NetWork——关于TCP协议的三次握手和四次挥手。
3.建立TCP连接后发起HTTP请求
TCP三次握手建立连接成功后,客户端按照指定的格式开始向服务端发送HTTP请求,服务端接收请求 后,解析HTTP请求,处理完业务逻辑,最后返回一个具有标准格式的HTTP响应给客户端。
3.1 HTTP请求格式
HTTP请求格式如下所示四部分组成,分别是请求行、请求头、空行、消息体,每部分内容占一行。请求行:由三部分组成:分别是请求方法(GET/POST/DELETE/PUT/HEAD)、 URI路径、 HTTP版本 号。 请求头:缓存相关信息(Cache-Control, If-Modified-Since)、客户端身份信息(User-Agent)、是 否支持gzip压缩,等键值对信息。 空行。 主体:客户端发给服务端的请求数据,这部分数据并不是每个请求必须的。
常用的GET、 POST、 PUT、 DELETE四种请求方式中:
(1)关于GET和DELETE将要处理的资源信息直接放在了URL中。通过"?键值对>&键值对>“的形式追 加。 HTTP RFC规范中并没有规定GET请求的URL长度,只是说明如果server无法处理太长的URI,可以 通过返回414状态码。但是大多数浏览器会讲其限制在2k-8k之间。 (2)关于POST和PUT的请求参数存储在报文的主体中。每一个参数都以”--boundary值“+"属性信息"+”
空行“+"参数值"的数据结构存储。请求数据的最后以”--boundary值--“的格式结尾。
3. 2 服务器响应HTTP请求 服务器接收处理完请求后返回一个HTTP响应消息给客户端。 HTTP响应消息的格式包括:状态行、响应 头、空行、消息体。每部分内容占一行。 状态行:有HTTP协议版本号,状态码和状态说明三部分构成。 响应头:用于说明数据的一些信息,比如数据类型、内容长度等键值对。 空行。 消息体:服务端返回给客户端的HTML文本内容。或者其他格式的数据,比如:视频流、图片或者音频 数据。
4.浏览器解析html代码,并请求html代码中的资源
浏览器拿到html文件后,就开始解析其中的html代码,遇到js/css/image等静态资源时,向服务器端发 起一个HTTP请求,如果服务器端返回304状态码(告诉浏览器服务器端没有修改该资源),那么浏览器 会直接读取本地的该资源的缓存文件。否则开启新线程向服务器端去请求下载。(这个时候就用上keepalive特性了,建立一次HTTP连接,可以请求多个资源。) 最后,浏览器利用自己内部的工作机制,把请求到的静态资源和html代码进行渲染,再呈现给用户。
2 Http网络请求方法
[] []
Http的请求方法代表了客户端想对服务器进行的操作,比如: POST、 GET、 HEAD、 PUT、 DELETE、
TRACE、 OPTIONS 。 常用的不过于CRUD四个。 增: PUT;删: DELETE;改: POST;查: GET。
2.1 GET 与 POST
GET
向服务器请求数据,获取资源,在大部分网络请求中, GET方法非常常见,并且它具有幂等性。
GET请求没有请求体,对于GET请求的请求参数在URL后面加上一个"?"的后面,参数以 key=val ue
的形式。参数与参数之间使用"&"进行连接。
GET请求是通过 URL 传输参数的,所以GET请求可以传输的参数是有限的。
POST
用于向表单提交数据,传送的数据放在请求体中。 在POST请求中,请求参数放在请求体中,服务器会根据POST请求体中的参数创建一个页面,然后 返回给客户端。 POST不具有幂等性。
POST 与 GET 区别
1 . 作用不同: GET 用于获取资源,而 POST 用于传输实体主体。
2. 参数位置不一样: GET 和 POST 的请求都能使用额外的参数,但是 GET 的参数是以查询字符串出 现在 URL 中,而 POST 的参数存储在实体主体中。但是并不是 POST 参数存储在实体主体中就认 为它的安全性更高,我们可以通过一些抓包工具如(Fiddler)查看。 在URL 只支持 ASCII 码,因此 GET 的参数中如果存在中文等字符就需要先进行编码。例如 中文 会 转换为 %E4%B8%AD%E6%96%87 ,而空格会转换为 %20 。 POST 支持标准字符集。
3. 安全性:安全的 HTTP 方法不会改变服务器状态,也就是说它只是可读的。 GET 方法是安全的, 而 POST 却不是,因为 POST 的目的是传送实体主体内容,这个内容可能是用户上传的表单数据, 上传成功之后,服务器可能把这个数据存储到数据库中,因此状态也就发生了改变。 安全的方法除了 GET 之外还有: HEAD、 OPTIONS。 不安全的方法除了 POST 之外还有 PUT、 DELETE。
1 . 幂等性: GET是幂等性,而POST不是幂等性。在正确实现的条件下, GET, HEAD, PUT,
OPTIONS 和 DELETE 等方法都是幂等的,而 POST 方法不是。 GET /pageX HTTP/1.1 是幂等的, 连续调用多次,客户端接收到的结果都是一样的: GET /pageX HTTP/1.1 GET /pageX HTTP/1.1 GET /pageX HTTP/1.1 GET /pageX HTTP/1.1
POST /add_row HTTP/1.1 不是幂等的,如果调用多次,就会增加多行记录: POST /add_row HTTP/1.1 -> Adds a 1nd row POST /add_row HTTP/1.1 -> Adds a 2nd row POST /add_row HTTP/1.1 -> Adds a 3rd row DELETE /idX/delete HTTP/1.1 是幂等的,即便不同的请求接收到的状态码不一样: DELETE /idX/delete HTTP/1.1 -> Returns 200 if idX exists DELETE /idX/delete HTTP/1.1 -> Returns 404 as it just got deleted DELETE /idX/delete HTTP/1.1 -> Returns 404
1 . 可缓存性: GET可以缓存,但是POST大部分情况下无法缓存。 如果要对响应进行缓存,需要满足 几个条件: 请求报文的 HTTP 方法本身是可缓存的,包括 GET 和 HEAD,但是 PUT 和 DELETE 不可缓存,
POST 在多数情况下不可缓存的。 响应报文的状态码是可缓存的,包括: 200 , 203 , 204 , 206 , 300 , 301 , 404 , 405 , 410 , 414, and 501。 响应报文的 Cache-Control 首部字段没有指定不进行缓存。
1 . 在使用 XMLHttpRequest 的 POST 方法时,浏览器会先发送 Header 再发送 Data。但并不是所有 浏览器会这么做,例如火狐就不会。而 GET 方法 Header 和 Data 会一起发送。
XMLHttpRequest 简介: XMLHttpRequest 是一个 API,它为客户端提供了在客户端和服务器之间 传输数据的功能。它提供了一个通过 URL 来获取数据的简单方式,并且不会使整个页面刷新。这 使得网页只更新一部分页面而不会打扰到用户,局部刷新避免资源浪费。并且XMLHttpRequest 在 AJAX 中被大量使用。
2.2 HEAD
获取报文首部,并且具有幂等性。 HEAD请求与GET请求一样,没有请求体。但是与GET区别在于,当使 用HEAD进行请求服务器时,服务器只返回响应头,不返回响应体。 常用于: - 检查请求的URL是否有 效,可以通过响应码进行判断 - 可以根据返回的响应头进行判断资源是否被篡改
2.3 PUT
用来向服务器上传文件,并且具有幂等性。与POST区别在于: POST用于向服务器发送数据,而PUT用 于向服务器储存数据。 它自身不带验证机制,导致任何人都可以上传文件,有很大的安全问题,一般不 使用该方法。 当使用PUT进行请求时,服务器会使用PUT的请求体的数据创建一个由它请求的URL命名 的新文件。没有进行特殊说明,一般PUT请求的请求体只用于创建或修改该资源上。如果请求的URL在 服务器中不存在,则根据该请求的主体部分创建一个由该请求URL命名的新文档;如果该URL在服务器 中已经存在,则用该主体替代他。
2.4 DELETE
用于删除服务器上的文件,并且具有幂等性。但是服务器并不是真正的删除文件,而是给需要删除的文 件做一个标记,与PUT功能相反。它也没有验证机制,有很大的安全问题。
2.5 PATCH
对资源进行部分修改。与PUT区别在于, PUT是修改所有资源,替代它,而PATCH只是修改部分资源。
2.6 OPTIONS
具有幂等性。当客户端不清楚对资源操作的方法,可以使用这个请求询问服务器该资源支持的请求方 法,在响应字段allow中返回,比如: Al l ow : GET , POST , HEAD 。它只可以在HTTP 1.1中使用。
2.7 TRACE
用来查看一个请求,经过网关,代理到达服务器,最后请求的变换。显示出请求到响应的传输路径。不 过有安全漏洞,会泄漏网站信息,被服务器禁止使用。仅在HTTP 1.1版本可以使用。
2.8 CONNECT
要求客户端与另一个远程服务器建立一个特殊的隧道,这时候web服务器充当代理角色。仅在HTTP 1.1
版本可以使用。 使用 SSL( Secu re Sockets Laye r,安全套接层) 和 TLS(Transpo rt Laye r Secu ri ty,传输层安全) 协议在网络隧道中进行加密传输。在介绍HTTP 请求方法之前,先来谈一下幂等 性,那什么是幂等性呢。
幂等性:指的是同样的请求不管执行多少次,效果都是一样,服务器状态也是一样的。具有幂等性 的请求方法没有副作用。 (统计用途除外)
Http——HttpURLConnection详解
Android设置网络权限
AndroidManifest.xml中添加
uses-permission android : name="android . permission . INTERNET" />
.1 HttpURLConnection简介
在JDK的 java.net 包中已经提供了访问HTTP协议的基本功能的类: HttpURLConnection。
HttpURLConnection是Java的标准类,它继承自 URLConnection,可用于向指定网站发送GET请求、
POST请求。 它在URLConnection的基础上提供了如下便捷的方法:
.2 HttpURLConnection使用
使用GET方式访问HTT
try {
URL url = new URL(“”);
//得到网络访问对象
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(false);
connection.setDoInput(true);
//设置请求方式
connection.setRequestMethod("GET");
//是否使用缓存
connection.setUseCaches(true);
// 设置此 HttpURLConnecti on 实例是否应该自动执行 HTTP 重定向
connection.setInstanceFollowRedirects(true);
// 设置三秒
connection.setConnectTimeout(3000);
//连接
connection.connect();
int code = connection.getResponseCode();
//如果返回码是200表示连接成功
if (code == 200) {
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
if ((line = reader.readLine()) != null) {
result += line;
}
reader.close();
}
//断开连接释放资源
connection.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return result;
用POST方式访问HTTP
try {
URL url = new URL(“”);
//得到网络访问对象
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(ture);
connection.setDoInput(true);
//设置请求方式
connection.setRequestMethod("POST");
//是否使用缓存
connection.setUseCaches(true);
// 设置此 HttpURLConnecti on 实例是否应该自动执行 HTTP 重定向
connection.setInstanceFollowRedirects(true);
// 设置三秒
connection.setConnectTimeout(3000);
//连接
OutputStream out=connection.getOutputStream();
out.write(param.getBytes());
out.flush();
connection.connect();
int code = connection.getResponseCode();
//如果返回码是200表示连接成功
if (code == 200) {
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
if ((line = reader.readLine()) != null) {
result += line;
}
reader.close();
}
//断开连接释放资源
connection.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return result;
HttpURLConnection说明
HttpURLConnection对象不能直接构造,需要通过URL类中的openConnection()方法来获得。 对HttpURLConnection对象的配置都需要在connect()方法执行之前完成,因为connect()会根据
HttpURLConnection对象的配置值生成HTTP头部信息。
HttpURLConnection的connect()函数,实际上只是建立了一个与服务器的TCP连接,并没有实际 发送HTTP请求。 **HTTP请求实际上直到我们获取服务器响应数据(如调用getInputStream()、
getResponseCode()等方法)时才正式发送出去**。
HttpURLConnection是基于HTTP协议的,其底层通过socket通信实现。如果不设置超时 (timeout),在网络异常的情况下,可能会导致程序僵死而不继续往下执行。
HTTP正文的内容是通过OutputStream流写入的, 向流中写入的数据不会立即发送到网络,而是 存在于内存缓冲区中,待流关闭时,根据写入的内容生成HTTP正文。 调用getInputStream()方法时,返回一个输入流,用于从中读取服务器对于HTTP请求的返回信息
我们可以使用HttpURLConnection.connect()方法手动的发送一个HTTP请求,但是如果要获取
HTTP响应的时候,请求就会自动的发起,比如我们使用HttpURLConnection.getInputStream()方 法的时候,所以完全没有必要调用connect()方法。
HttpURLConnection长连接(Keep-Alive)
JDK8自带的HttpURLConnection,默认启用keepAlive,支持HTTP / 1.1和HTTP / 1.0持久连接, 使用后的HttpURLConnection会放入缓存中供以后的同host:port的请求重用,底层的socket在
keepAlive超时之前不会关闭。
HttpURLConnection受以下system properties控制:
http . keepAl i ve=(默认值: t rue) ,是否启用keepAlive,如果设置为false,则
HttpURLConnection不会缓存,使用完后会关闭socket连接。
http . maxConnecti ons=(默认值: 5) ,每个目标host缓存socket连接的最大数。
说明:
1 . 如果在HttpURLConnection的header中加入Connection: close,则此连接不会启用keepAlive 2. 想要启用keepAlive,程序请求完毕后,必须调用HttpURLConnection.getInputStream().close()
(表示归还长连接给缓存,以供下次同host : po rt的请求重用底层socket连接) ,而不能调用
HttpURLConnection.disconnect() (表示关闭底层socket连接,不会启用 keepAl i ve)
3. keepAliveTimeout首先从http response header中获取,如果没有取到,则默认为5秒,
sun.net.www.http.KeepAliveCache.java中有一个线程,每5秒执行一次,检查缓存的连接的空闲 时间是否超过keepAliveTimeout,如果超过则关闭连接。从KeepAliveCache中获取缓存的连接时 也会检查获取到的连接的空闲时间是否超过keepAliveTimeout,如果超过则关闭连接,并且获取 下一个连接,再执行以上检查,直达获取到空闲时间在keepAliveTimeout以内的缓存连接为此。
3.5 HttpURLConnection关闭
本身要 HttpURLConnection 是很简单的,调用 connecti on . di sconnect () 就可以了。 这里是想说明一下,是否需要关闭,应该根据实际需要来: 当 HttpURLConnection 是 "Connection: close " 模式,那么关闭 inputStream 后就会自动断开连 接。 当 HttpURLConnection 是 "Connection: Keep-Alive" 模式,那么关闭 inputStream 后,并不会断 开底层的 Socket 连接。这样的好处,是当需要连接到同一服务器地址时,可以复用该 Socket。这 时如果要求断开连接,就可以调用 connecti on . di sconnect () 了。 当然, HttpURLConnection 连接到底是不是 Keep-Alive 模式,除了 HttpURLConnection 请求设置为 Keep-Alive 外 (http 1.0中默认是关闭的, http 1.1中默认启用Keep-Alive),也需要服务器支持 KeepAlive,才可以真正建立 Keep-Alive 连接。
3.6 与HttpClient的区别
在一般情况下,如果只是需要向Web站点的某个简单页面提交请求并获取服务器响应,
HttpURLConnection完全可以胜任。但在绝大部分情况下,
Web站点的网页可能没这么简单,这些页面并不是通过一个简单的URL就可访问的,可能需要用户 登录而且具有相应的权限才可访问该页面。 在这种情况下,就需要涉及Session、 Cookie的处理了,如果打算使用HttpURLConnection来处理 这些细节,当然也是可能实现的,只是处理起来难度就大了。为了更好地处理向Web站点请求,包括处理Session、 Cookie等细节问题, Apache开源组织提供了 一个HttpClient项目,看它的名称就知道, 它是一个简单的HTTP客户端(并不是浏览器),可以用于发送HTTP请求,接收HTTP响应。但不 会缓存服务器的响应, 不能执行HTML页面中嵌入的Javascript代码;也不会对页面内容进行任何解析、处理。 简单来说, HttpClient就是一个增强版的HttpURLConnection, HttpURLConnection可以做的事情
HttpClient全部可以做;
HttpURLConnection没有提供的有些功能, HttpClient也提供了,但它只是关注于如何发送请求、 接收响应,以及管理HTTP连接。
4 JSON
Json(Javascript Object notation)作为一种轻量级的数据传输格式,在现代软件开发中广泛使用,采用完 全独立于语言的文本格式,具有可读性强、编写容易,更利于机器的解析与生成。
4.1 JSON与Xml的比较
Json与xml分别作为轻量级的数据传输格式,在软件开发中有着很重要的作用,同时两者在不同的编程 语言中能够很容易的解析与生成。根据自身的优缺点,在实际项目的开发中,选择合适的数据传输格式 尤为重要,比较如下
Json与xml具有极为丰富的解析方式
Json与xml比较, json的数据小
Json与xml比较, xml能够更好的描述对象
Json与xml比较, json的传输效率更高
Json与xml比较,在编写方面, xml具有丰富的工具编写
4.2 JSON的结构
JSON具有以下这些表现形式
对象(JSONObject):
对象是一个无序的“‘名称/值’对”集合。一个对象以“{”(左括号)开始,“}”(右括号)结束。每个“名称”后跟一个
“:”(冒号);“‘名称/值’ 对”之间使用“,”(逗号)分隔。
JSONObject结构图
数组(JSONArray):
数组是值(value)的有序集合。一个数组以“[”(左中括号)开始,“]”(右中括号)结束。值之间使用“,”(逗号)分 隔。
JSON的使用
1.生成JSONObject
2.解析JsonObject
生成JSONArray
JsonObject obj =new JsonObjec
解析json
try {
JSONObject object=new JSONObject(result);
JSONArray array=object.getJSONArray("data");
for (int i = 0; i < array.length(); i++) {
JSONObject object1=array.getJSONObject(i);
String title=object1.getString("title");
String desc=object1.getString("desc");
String pic=object1.getString("pic");
News news=new News(title,desc,pic);
Log.i("json解析",news.toString());
list.add(news);
}
NewsAdapter newsAdapter=new NewsAdapter(list);
LinearLayoutManager layoutManager=new LinearLayoutManager(MainActivity3.this);
rv_show.setLayoutManager(layoutManager);
rv_show.setAdapter(newsAdapter);
} catch (JSONException e) {