Android https网络编程协议 双向验证 报文 请求体 响应头(自定义okhttp框架)

  1. http的结构,http1.0和2.0区别  tcp协议  请求体和响应行(搞定)
  2. 常用的状态码(搞定)
  3. get请求和post请求区别(搞定)
  4. https 加密流程,对称加密和非对称加密(搞定)

  5. 双向验证和单项验证(搞定)

  6. 三次握手的流程(搞定)

  7. 网络请求取消

  8. okhttp的原理(搞定)

  9. 网络优化

  10. Cookie与Session的作用于原理? 
  11. 长连接
  12. 什么是Nginx?为什么使用Nginx?
  13. 手机段搭建局域网===搭建服务器。
  14. .nio多路复用

问题

1.http的状态妈?常见的请求头?http缓存协议,https如何加密?

2.http的报文结构,cookies是什么?哪些响应码有哪些?

3.所以Get与Post区别本质就是参数是放在请求行中还是放在请求体

 

HTTP请求报文解剖 

HTTP请求报文由3部分组成(请求行+请求头+请求体): 

 

下面是一个实际的请求报文: 

 
 



①是请求方法,GET和POST是最常见的HTTP方法,除此以外还包括DELETE、HEAD、OPTIONS、PUT、TRACE。不过,当前的大多数浏览器只支持GET和POST,Spring 3.0提供了一个HiddenHttpMethodFilter,允许你通过“_method”的表单参数指定这些特殊的HTTP方法(实际上还是通过POST提交表单)。服务端配置了HiddenHttpMethodFilter后,Spring会根据_method参数指定的值模拟出相应的HTTP方法,这样,就可以使用这些HTTP方法对处理方法进行映射了。 

②为请求对应的URL地址,它和报文头的Host属性组成完整的请求URL,③是协议名称及版本号。 

④是HTTP的报文头,报文头包含若干个属性,格式为“属性名:属性值”,服务端据此获取客户端的信息。 

⑤是报文体,它将一个页面表单中的组件值通过param1=value1&param2=value2的键值对形式编码成一个格式化串,它承载多个请求参数的数据。不但报文体可以传递请求参数,请求URL也可以通过类似于“/chapter15/user.html? param1=value1&param2=value2”的方式传递请求参数。 

对照上面的请求报文,我们把它进一步分解,你可以看到一幅更详细的结构图: 

 

认识Http协议

 

Android中发送http网络请求是很常见的,要有GET请求和POST请求。一个完整的http请求需要经历两个过程:客户端发送请求到服务器,然后服务器将结果返回给客户端,如下图所示: 

 

 

客户端->服务器 

客户端向服务器发送请求主要包含以下信息:请求的Url地址、请求头以及可选的请求体,打开百度首页,客户端向服务器发送的信息如下所示:

 

 

 

请求URL(Request URL) 

上图中的Request URL就是请求的Url地址,即https://www.baidu.com,该Url没有附加其他的参数。其实可以通过?和&符向URL地址后面追加一系列的键值对参数,比如地址https://www.baidu.com/s?ie=utf-8&wd=Android,该Url包含两个键值对,ie=utf-8,以及wd=Android,ie和wd是key,utf-8和Android分别是其对应的value,服务端可以获取ie和wd所对应的value的值。由此我们可以看出,Url可以携带额外的数据信息。一般情况下,URL的长度不能超过2048个字符,即2KB,超过此限制的话服务器可能就不识别。

 

请求头(Request Headers) 

上图中Request Headers部分就是请求头,请求头其实也是一些键值对,不过这些键值通常都是W3C定义了的一些标准的Http请求头的名称,请求头包含了客户端想告诉服务端的一些元数据信息,注意是元数据,而不是数据,比如请求头User-Agent会告诉服务器这条请求来自于什么浏览器,再比如请求头Accept-Encoding会告诉服务器客户端支持的压缩格式。除了这些标准的请求头,我们还可以添加自定义的请求头。

 

请求体(Request Body) 

之前我们提到,URL的最大长度就是2048个字符,如果我们发送的数据很大,超过了2KB怎么办?我们可以将很大的数据放到请求体中,GET请求不支持请求体,只有POST请求才能设置请求体。请求体中可以放置任意的字节流,从而可以很方便地发送任意格式的数据,服务端只需要读取该输入流即可。

 

服务器->客户端 

服务器接收到客户端发来的请求后,会进行相应的处理,并向客户端输出信息,输出的信息包括响应头和响应体。

 

响应头 (Response Headers) 

响应头也是一些键值对,如下所示: 

 

 

响应头包含了服务器想要告诉客户端的一些元数据信息,注意不是数据,是元数据,比如通过响应头Content-Encoding告诉客户端服务器所采用的压缩格式,响应头Content-Type告诉客户端响应体是什么格式的数据,再比如服务端可以通过多个Set-Cookie响应头向客户端写入多条Cookie信息,等等。刚刚提到的几个请求头都是W3C规定的标准的请求头名称,我们也可以在服务端向客户端写入自定义的响应头。

 

响应体 (Response Body) 

响应体是服务端向客户端传输的实际的数据信息,本质就是一堆字节流,可以表示文本,也可以表示图片或者其他格式的信息,如下所示: 

 

 

GET vs POST

 

Http协议支持的操作有GET、POST、HEAD、PUT、TRACE、OPTIONS、DELETE,其中最最常用的还是GET和POST操作,下面我们看一下GET和POST的区别。

 

GET:

 

GET请求可以被缓存。

我们之前提到,当发送键值对信息时,可以在URL上面直接追加键值对参数。当用GET请求发送键值对时,键值对会随着URL一起发送的。

由于GET请求发送的键值对时随着URL一起发送的,所以一旦该URL被黑客截获,那么就能看到发送的键值对信息,所以GET请求的安全性很低,不能用GET请求发送敏感的信息(比如用户名密码)。

由于URL不能超过2048个字符,所以GET请求发送数据是有长度限制的。

由于GET请求较低的安全性,我们不应该用GET请求去执行增加、删除、修改等的操作,应该只用它获取数据。

POST:

 

POST请求从不会被缓存。

POST请求的URL中追加键值对参数,不过这些键值对参数不是随着URL发送的,而是被放入到请求体中发送的,这样安全性稍微好一些。

应该用POST请求发送敏感信息,而不是用GET。

由于可以在请求体中发送任意的数据,所以理论上POST请求不存在发送数据大小的限制。

当执行增减、删除、修改等操作时,应该使用POST请求,而不应该使用GET请求。

--------------------- 

引用

HttpWatch是强大的网页数据分析工具,安装后将集成到Internet Explorer工具栏中。它不用代理服务器或一些复杂的网络监控工具,就能抓取请求及响应的完整信息,包括Cookies、消息头、查询参数、响应报文等,是Web应用开发人员的必备工具。



HTTP请求报文头属性 

报文头属性是什么东西呢?我们不妨以一个小故事来说明吧。 
 

引用

快到中午了,张三丰不想去食堂吃饭,于是打电话叫外卖:老板,我要一份[鱼香肉丝],要12:30之前给我送过来哦,我在江湖湖公司研发部,叫张三丰。



这里,你要[鱼香肉丝]相当于HTTP报文体,而“12:30之前送过来”,你叫“张三丰”等信息就相当于HTTP的报文头。它们是一些附属信息,帮忙你和饭店老板顺利完成这次交易。 

请求HTTP报文和响应HTTP报文都拥有若干个报文关属性,它们是为协助客户端及服务端交易的一些附属信息。 


常见的HTTP请求报文头属性 

Accept 

请求报文可通过一个“Accept”报文头属性告诉服务端 客户端接受什么类型的响应。 

如下报文头相当于告诉服务端,俺客户端能够接受的响应类型仅为纯文本数据啊,你丫别发其它什么图片啊,视频啊过来,那样我会歇菜的~~~: 
 

Java代码  

  1. Accept:text/plain  



Accept属性的值可以为一个或多个MIME类型的值,关于MIME类型,大家请参考:http://en.wikipedia.org/wiki/MIME_type 

Cookie 

客户端的Cookie就是通过这个报文头属性传给服务端的哦!如下所示: 

Java代码  

  1. Cookie: $Version=1; Skin=new;jsessionid=5F4771183629C9834F8382E23BE13C4C  


服务端是怎么知道客户端的多个请求是隶属于一个Session呢?注意到后台的那个jsessionid=5F4771183629C9834F8382E23BE13C4C木有?原来就是通过HTTP请求报文头的Cookie属性的jsessionid的值关联起来的!(当然也可以通过重写URL的方式将会话ID附带在每个URL的后面哦)。 


Referer 

表示这个请求是从哪个URL过来的,假如你通过google搜索出一个商家的广告页面,你对这个广告页面感兴趣,鼠标一点发送一个请求报文到商家的网站,这个请求报文的Referer报文头属性值就是http://www.google.com。 

引用


唐僧到了西天. 
如来问:侬是不是从东土大唐来啊? 
唐僧:厉害!你咋知道的! 
如来:呵呵,我偷看了你的Referer... 



很多貌似神奇的网页监控软件(如著名的 我要啦),只要在你的网页上放上一段JavaScript,就可以帮你监控流量,全国访问客户的分布情况等报表和图表,其原理就是通过这个Referer及其它一些HTTP报文头工作的。 

Cache-Control 

对缓存进行控制,如一个请求希望响应返回的内容在客户端要被缓存一年,或不希望被缓存就可以通过这个报文头达到目的。 

如以下设置,相当于让服务端将对应请求返回的响应内容不要在客户端缓存: 

Java代码  

  1. Cache-Control: no-cache  



其它请求报文头属性 

参见:http://en.wikipedia.org/wiki/List_of_HTTP_header_fields 

如何访问请求报文头 

由于请求报文头是客户端发过来的,服务端当然只能读取了,以下是HttpServletRequest一些用于读取请求报文头的API: 
 

Java代码  

  1. //获取请求报文中的属性名称  
  2. java.util.Enumeration<java.lang.String>   getHeaderNames();  
  3.   
  4. //获取指定名称的报文头属性的值  
  5. java.lang.String getHeader(java.lang.String name)   



由于一些请求报文头属性“太著名”了,因此HttpServletRequest为它们提供了VIP的API: 
 

Java代码  

  1. //获取报文头中的Cookie(读取Cookie的报文头属性)  
  2.  Cookie[]   getCookies() ;  
  3.   
  4. //获取客户端本地化信息(读取 Accept-Language 的报文头属性)  
  5. java.util.Locale    getLocale()   
  6.   
  7. //获取请求报文体的长度(读取Content-Length的报文头属性)  
  8. int getContentLength();  



HttpServletRequest可以通过 

Java代码  

  1. HttpSession getSession()   


获取请求所关联的HttpSession,其内部的机理是通过读取请求报文头中Cookie属性的JSESSIONID的值,在服务端的一个会话Map中,根据这个JSESSIONID获取对应的HttpSession的对象。(这样,你就不会觉得HttpSession很神秘了吧,你自己也可以做一个类似的会话管理  ) 

HTTP响应报文解剖 

响应报文结构 

HTTP的响应报文也由三部分组成(响应行+响应头+响应体): 

 

以下是一个实际的HTTP响应报文: 

 

①报文协议及版本; 
②状态码及状态描述; 
③响应报文头,也是由多个属性组成; 
④响应报文体,即我们真正要的“干货”。 

响应状态码 

和请求报文相比,响应报文多了一个“响应状态码”,它以“清晰明确”的语言告诉客户端本次请求的处理结果。 

HTTP的响应状态码由5段组成: 
 

  • 1xx 消息,一般是告诉客户端,请求已经收到了,正在处理,别急...
  • 2xx 处理成功,一般表示:请求收悉、我明白你要的、请求已受理、已经处理完成等信息.
  • 3xx 重定向到其它地方。它让客户端再发起一个请求以完成整个处理。
  • 4xx 处理发生错误,责任在客户端,如客户端的请求一个不存在的资源,客户端未被授权,禁止访问等。
  • 5xx 处理发生错误,责任在服务端,如服务端抛出异常,路由出错,HTTP版本不支持等。



以下是几个常见的状态码: 

200 OK 

你最希望看到的,即处理成功! 

303 See Other 

我把你redirect到其它的页面,目标的URL通过响应报文头的Location告诉你。 

引用

悟空:师傅给个桃吧,走了一天了 
唐僧:我哪有桃啊!去王母娘娘那找吧



304 Not Modified 

告诉客户端,你请求的这个资源至你上次取得后,并没有更改,你直接用你本地的缓存吧,我很忙哦,你能不能少来烦我啊! 

404 Not Found 

你最不希望看到的,即找不到页面。如你在google上找到一个页面,点击这个链接返回404,表示这个页面已经被网站删除了,google那边的记录只是美好的回忆。 

500 Internal Server Error 

看到这个错误,你就应该查查服务端的日志了,肯定抛出了一堆异常,别睡了,起来改BUG去吧! 


其它的状态码参见:http://en.wikipedia.org/wiki/List_of_HTTP_status_codes 


有些响应码,Web应用服务器会自动给生成。你可以通过HttpServletResponse的API设置状态码: 
 

Java代码  

  1. //设置状态码,状态码在HttpServletResponse中通过一系列的常量预定义了,如SC_ACCEPTED,SC_OK  
  2. void    setStatus(int sc)   



常见的HTTP响应报文头属性 

Cache-Control 

响应输出到客户端后,服务端通过该报文头属告诉客户端如何控制响应内容的缓存。 

下面,的设置让客户端对响应内容缓存3600秒,也即在3600秒内,如果客户再次访问该资源,直接从客户端的缓存中返回内容给客户,不要再从服务端获取(当然,这个功能是靠客户端实现的,服务端只是通过这个属性提示客户端“应该这么做”,做不做,还是决定于客户端,如果是自己宣称支持HTTP的客户端,则就应该这样实现)。 
 

Java代码  

  1. Cache-Control: max-age=3600  



ETag 

一个代表响应服务端资源(如页面)版本的报文头属性,如果某个服务端资源发生变化了,这个ETag就会相应发生变化。它是Cache-Control的有益补充,可以让客户端“更智能”地处理什么时候要从服务端取资源,什么时候可以直接从缓存中返回响应。 

关于ETag的说明,你可以参见:http://en.wikipedia.org/wiki/HTTP_ETag。 
Spring 3.0还专门为此提供了一个org.springframework.web.filter.ShallowEtagHeaderFilter(实现原理很简单,对JSP输出的内容MD5,这样内容有变化ETag就相应变化了),用于生成响应的ETag,因为这东东确实可以帮助减少请求和响应的交互。 

下面是一个ETag: 

Java代码  

  1. ETag: "737060cd8c284d8af7ad3082f209582d"  



Location 

我们在JSP中让页面Redirect到一个某个A页面中,其实是让客户端再发一个请求到A页面,这个需要Redirect到的A页面的URL,其实就是通过响应报文头的Location属性告知客户端的,如下的报文头属性,将使客户端redirect到iteye的首页中: 
 

Java代码  

  1. Location: http://www.iteye.com  



Set-Cookie 

服务端可以设置客户端的Cookie,其原理就是通过这个响应报文头属性实现的: 
 

Java代码  

  1. Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1  




其它HTTP响应报文头属性 

更多其它的HTTP响应头报文,参见:http://en.wikipedia.org/wiki/List_of_HTTP_header_fields 


如何写HTTP请求报文头 

在服务端可以通过HttpServletResponse的API写响应报文头的属性: 
 

Java代码  

  1. //添加一个响应报文头属性  
  2. void    setHeader(String name, String value)   



象Cookie,Location这些响应都是有福之人,HttpServletResponse为它们都提供了VIP版的API: 

Java代码  

  1. //添加Cookie报文头属性  
  2. void addCookie(Cookie cookie)   
  3.   
  4. //不但会设置Location的响应报文头,还会生成303的状态码呢,两者天仙配呢  
  5. void    sendRedirect(String location)   


 

来源: https://blog.csdn.net/u010256388/article/details/68491509

 

 

HTTP响应头和请求头信息对照表

HTTP请求头提供了关于请求,响应或者其他的发送实体的信息。HTTP的头信息包括通用头、请求头、响应头和实体头四个部分。每个头域由一个域名,冒号(:)和域值三部分组成。

  • 通用头标:即可用于请求,也可用于响应,是作为一个整体而不是特定资源与事务相关联。
  • 请求头标:允许客户端传递关于自身的信息和希望的响应形式。
  • 响应头标:服务器和于传递自身信息的响应。
  • 实体头标:定义被传送资源的信息。即可用于请求,也可用于响应。

根据以上分类的HTTP请求头介绍可以参考此文,本工具根据请求和输出分为Request和Response两部分。

 

 

 

 

 

 

参考博客

 

okhttp的原理

https://www.jianshu.com/p/9ed2c2f2a52c

https://blog.csdn.net/json_it/article/details/78404010

 

 

 

安卓系列(完结)

https://blog.csdn.net/itachi85/article/details/50982995

https://www.jianshu.com/p/3141d4e46240

 

 

基本架构(ok)

https://www.cnblogs.com/smyhvae/p/4004983.html

 

 

 

 

:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记

 

 

HTTP URL 的格式

 

http://host[":"port][abs_path]1://host[":"port][abs_path]1

http表示要通过HTTP协议来定位网络资源; 
host表示合法的Internet主机域名或者IP地址; 
port指定一个端口号,为空则使用默认端口80; 
abs_path指定请求资源的URI(Web上任意的可用资源)。

 

 

 

请求报文:

 

GET http://blog.csdn.net/itachi85 HTTP/1.1                                //请求行Host: blog.csdn.net                                                       //请求报头Connection: keep-alive http://blog.csdn.net/itachi85 HTTP/1.1                                //请求行Host: blog.csdn.net                                                       //请求报头Connection: keep-alive
Cache-Control: max-age=0       Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8-Control: max-age=0       Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36 QQBrowser/9.3.6872.400
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8
Cookie: bdshare_firstime=1443768140949; uuid_tt_dd=5028529250430960147_20151002;
...省略

 

 

 

 

响应报文:

 

HTTP/1.1 200 OK                                                         //状态行Server: openresty                                                       //响应报头Date: Sun, 27 Mar 2016 08:26:54 GMT/1.1 200 OK                                                         //状态行Server: openresty                                                       //响应报头Date: Sun, 27 Mar 2016 08:26:54 GMT
Content-Type: text/html; charset=utf-8Transfer-Encoding: chunked-Type: text/html; charset=utf-8Transfer-Encoding: chunked
Connection: keep-alive: keep-alive
Keep-Alive: timeout=20Vary: Accept-Encoding-Alive: timeout=20Vary: Accept-Encoding
Cache-Control: privateX-Powered-By: PHP 5.4.28-Control: privateX-Powered-By: PHP 5.4.28
Content-Encoding: gzip-Encoding: gzip
                                                                        //不能省略的空格//不能省略的空格
 b5                                    
 ysI   1ߡFsgl n- ]{^_ { 'z!     C ,  m# 0 !l   `  4x  ly .ݪ*  
  ڴzAt_Xl *  9'O  ɬ  '•  ק   3  ^1aڴzAt_Xl *  9'O  ɬ  '•  ק   3  ^1a
...省略省略


 

 

 

 

 

 

 

分析上图,步骤如下:

  • 第一步:在浏览器客户端中得到用户输入的内容。 

  • 第二步:浏览器得到这个网址之后,内部会将这个域名发送到DNS上,进行域名解析。得到它的IP之后就会链接到指定的服务器上,假如服务器的地址是:221.104.13.32:80,从浏览器到服务器端口它使用到最底层的TCP/IP协议。 

  • 第三步:实现TCP/IP协议用Socket来完成,使用了Socket的套接字。 

  • 第四步:服务器端的80端口监听客户端的链接,这样客户端到服务器就链接上了。

  • 服务器接收到这些内容之后,并按照这些请求的路径找到对应的页面,进一步找到对应的网页内容,返回给客户端。

通俗一点讲,用户在浏览器输入网址,通过http协议发出去,网址经过DNS域名解析,解析成指定的ip地址,并在80端口上监听用户的请求。服务器监听到请求之后,会以三种方式返回给客户端:HTML、XML、JASON。

 

 

 

 

 

 

 

Apache的HttpClient和Java的HttpURLConnection

 

所以在Android 2.2版本以及之前的版本使用HttpClient是较好的选择,而在Android 2.3版本及以后,HttpURLConnection则是最佳的选择,它的API简单,体积较小,因而非常适用于Android项目。压缩和缓存机制可以有效地减少网络访问的流量,在提升速度和省电方面也起到了较大的作用。另外在Android 6.0版本中,HttpClient库被移除了,HttpURLConnection则是以后我们唯一的选择。

 

HttpURLConnection的API提供的比较简单,但是同时这也使得我们可以更加容易地去使用和扩展它。

 

 

参考博客:

http://blog.csdn.net/u010256388/article/details/68491509

 

https的加密过程


 

https的地址:

https://www.cnblogs.com/zhangshitong/p/6478721.html

 

双向验证

https://blog.csdn.net/ustccw/article/details/76691248

 

 

有一种称为“非对称加密”的加密算法,特点是私钥加密后的密文,只要是公钥,都可以解密,但是公钥加密后的密文,只有私钥可以解密。私钥只有一个人有,而公钥可以发给所有的人

 

问题的难点是如果我们选择直接将公钥传递给客户端的方案,我们始终无法解决公钥传递被中间人调包的问题。

所以,我们不能直接将服务器的公钥传递给客户端,而是第三方机构使用它的私钥对我们的公钥进行加密后,再传给客户端。客户端再使用第三方机构的公钥进行解密。

下图就是我们设计的第一版“数字证书”,证书中只有服务器交给第三方机构的公钥,而且这个公钥被第三方机构的私钥加密了:

HTTPS简介

  HTTPS其实是有两部分组成:HTTP + SSL / TLS,也就是在HTTP上又加了一层处理加密信息的模块。服务端和客户端的信息传输都会通过TLS进行加密,所以传输的数据都是加密后的数据。具体是如何进行加密,解密,验证的,且看下图。

  1. 客户端发起HTTPS请求

  这个没什么好说的,就是用户在浏览器里输入一个https网址,然后连接到server的443端口。

  2. 服务端的配置

  采用HTTPS协议的服务器必须要有一套数字证书,可以自己制作,也可以向组织申请。区别就是自己颁发的证书需要客户端验证通过,才可以继续访问,而使用受信任的公司申请的证书则不会弹出提示页面(startssl就是个不错的选择,有1年的免费服务)。这套证书其实就是一对公钥和私钥。如果对公钥和私钥不太理解,可以想象成一把钥匙和一个锁头,只是全世界只有你一个人有这把钥匙,你可以把锁头给别人,别人可以用这个锁把重要的东西锁起来,然后发给你,因为只有你一个人有这把钥匙,所以只有你才能看到被这把锁锁起来的东西。

  3. 传送证书

  这个证书其实就是公钥,只是包含了很多信息,如证书的颁发机构,过期时间等等。

  4. 客户端解析证书

  这部分工作是有客户端的TLS来完成的,首先会验证公钥是否有效,比如颁发机构,过期时间等等,如果发现异常,则会弹出一个警告框,提示证书存在问题。如果证书没有问题,那么就生成一个随机值。然后用证书对该随机值进行加密。就好像上面说的,把随机值用锁头锁起来,这样除非有钥匙,不然看不到被锁住的内容。

  5. 传送加密信息

  这部分传送的是用证书加密后的随机值,目的就是让服务端得到这个随机值,以后客户端和服务端的通信就可以通过这个随机值来进行加密解密了。

  6. 服务段解密信息

 服务器用私钥解密,得到客户端的随机值是非对称加密

对称加密:内容传输的时候

  服务端用私钥解密后,得到了客户端传过来的随机值(私钥),然后把内容通过该值进行对称加密。所谓对称加密就是,将信息和私钥通过某种算法混合在一起,这样除非知道私钥,不然无法获取内容,而正好客户端和服务端都知道这个私钥,所以只要加密算法够彪悍,私钥够复杂,数据就够安全。

  7. 传输加密后的信息

  这部分信息是服务段用私钥加密后的信息,可以在客户端被还原。

  8. 客户端解密信息

  客户端用之前生成的私钥解密服务段传过来的信息,于是获取了解密后的内容。整个过程第三方即使监听到了数据,也束手无策

来源: https://blog.csdn.net/firehive/article/details/81560425

 

网络请求的加密

1.body对象都经过加密

2.head对象不会

 

 要说明什么是双向认证,就先说明什么是单向认证。

    1:在普通的场景中,例如我们访问https://www.baidu.com,客户端会和服务器会进行SSL握手,进行密钥协商与身份认证,这个身份认证就是单向认证,又叫服务器认证,即 客户端需要认证服务器身份,客户端如何认证服务器身份呢?

 

单向验证过程中,客户端会验证自己访问的服务器,服务器对来访的客户端身份不做任何限制。如果服务器需要限制客户端的身份,则可以选择开启服务端验证,这就是双向验证。从这个过程中我们不难发现,使用单向验证还是双向验证,是服务器决定的。

 

总结一下:

1、单向验证中,如果是你客户端,你需要拿到服务器的证书,并放到你的信任库中;如果是服务端,你要生成私钥和证书,并将这两个放到你的密钥库中,并且将证书发给所有客户端。

2、双向验证中,如果你是客户端,你要生成客户端的私钥和证书,将它们放到密钥库中,并将证书发给服务端,同时,在信任库中导入服务端的证书。如果你是服务端,除了在密钥库中保存服务器的私钥和证书,还要在信任库中导入客户端的证书。

3、再次强调,使用单向验证还是双向验证,是服务器决定的。

 

TCP三次握手

 

        

 

第一次握手

 

        建立连接。客户端发送连接请求报文段,将SYN位置为1,Sequence Number为x;然后,客户端进入SYN_SEND状态,等待服务器的确认;

 

第二次握手

 

        服务器收到SYN报文段。服务器收到客户端的SYN报文段,需要对这个SYN报文段进行确认,设置Acknowledgment Number为x+1(Sequence Number+1);同时,自己自己还要发送SYN请求信息,将SYN位置为1,Sequence Number为y;服务器端将上述所有信息放到一个报文段(即SYN+ACK报文段)中,一并发送给客户端,此时服务器进入SYN_RECV状态;

 

第三次握手

 

       客户端收到服务器的SYN+ACK报文段。然后将Acknowledgment Number设置为y+1,向服务器发送ACK报文段,这个报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED状态,完成TCP三次握手。

 

 

为什么要三次握手

 

为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。

 

 

具体例子:“已失效的连接请求报文段”的产生在这样一种情况下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。”

 

 

 

七、四次挥手

 

 

 

第一次分手

 

       主机1(可以使客户端,也可以是服务器端),设置Sequence Number,向主机2发送一个FIN报文段;此时,主机1进入FIN_WAIT_1状态;这表示主机1没有数据要发送给主机2了;

 

第二次分手

 

       主机2收到了主机1发送的FIN报文段,向主机1回一个ACK报文段,Acknowledgment Number为Sequence Number加1;主机1进入FIN_WAIT_2状态;主机2告诉主机1,我“同意”你的关闭请求;

 

第三次分手

 

       主机2向主机1发送FIN报文段,请求关闭连接,同时主机2进入LAST_ACK状态;

 

第四次分手

 

       主机1收到主机2发送的FIN报文段,向主机2发送ACK报文段,然后主机1进入TIME_WAIT状态;主机2收到主机1的ACK报文段以后,就关闭连接;此时,主机1等待2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,主机1也可以关闭连接了。

 

 

为什么要四次分手

       TCP协议是一种面向连接的、可靠的、基于字节流的运输层通信协议。TCP是全双工模式,这就意味着,当主机1发出FIN报文段时,只是表示主机1已经没有数据要发送了,主机1告诉主机2,它的数据已经全部发送完毕了;但是,这个时候主机1还是可以接受来自主机2的数据;当主机2返回ACK报文段时,表示它已经知道主机1没有数据发送了,但是主机2还是可以发送数据到主机1的;当主机2也发送了FIN报文段时,这个时候就表示主机2也没有数据要发送了,就会告诉主机1,我也没有数据要发送了,之后彼此就会愉快的中断这次TCP连接。

 

什么是Nginx?为什么使用Nginx?

地址:

https://blog.csdn.net/x324235r325/article/details/78518042

 

网络优化

进过分析,xutils框架在网络调用方面表现不如retrofit2+okhttp3,替换它能够优化网络调用的性能,并且会有较低的内存。

我们先对比一下使用Xutils3 和Retrofit + OkHttp3的网络框架处理网络请求的TraceView。

4.2 IP直连与HttpDns;

DNS解析的失败率占联网失败中很大一种,而且首次域名解析一般需要几百毫秒。针对此,我们可以不用域名,才用IP直连省去 DNS 解析过程,节省这部分时间。

另外熟悉阿里云的小伙伴肯定知道HttpDns:HttpDNS基于Http协议的域名解析,替代了基于DNS协议向运营商Local DNS发起解析请求的传统方式,可以避免Local DNS造成的域名劫持和跨网访问问题,解决域名解析异常带来的困扰。

 

 

http请求的原生页面

header:

conn.setRequestProperty("bkatimestamp",timeStampToken.timeStamp);

Body:通过流写进去

conn.setReadTimeout();
os = conn.getOutputStream();
 os.write(jsonRequest.getBytes());

 

post(isHttps, Activity activity, String url, String jsonRequest, CallBack callBack) {
    BALog.(url + + jsonRequest);
    OutputStream os = ;
    BufferedReader br = ;
    HttpURLConnection conn = ;
    {
        (isHttps) {
            conn = (url, -);
        } {
            conn = (url, -);
        }
        (activity != ) {

            activity.runOnUiThread(Runnable() {
                run() {
                    LoadingManager.(, , , , );
                }
            });
        }
        (conn == ) {
            BALog.(url + + );
            (callBack != ) {
                callBack.onFail();
            }
            ;
        }
        (!TextUtils.(jsonRequest)) {
            isNeedTicket = BKAConfig.(url);
            BKACoreUtil.TimeStampToken timeStampToken = BKACoreUtil.(isNeedTicket);
            conn.setRequestProperty(,timeStampToken.);
            conn.setRequestProperty(,timeStampToken.);
            conn.setRequestProperty(,NetWorkUtils.());
            (isNeedTicket) {
                conn.setRequestProperty(, BKAAppCoreInfo.().getTicket());
            }
            conn.setRequestProperty(, DeviceUtil.());
            conn.setRequestMethod();
            conn.setConnectTimeout();
            conn.setReadTimeout();
            os = conn.getOutputStream();
            os.write(jsonRequest.getBytes());
            os.close();
        }
        responseCode = conn.getResponseCode();
        String responseMessage = conn.getResponseMessage();
        (responseCode != ) {
            BALog.(url + + responseCode);
            (callBack != ) {
                callBack.onFail(responseCode);
            }
        } {
            br = BufferedReader(InputStreamReader(conn.getInputStream()));
            StringBuffer sb = StringBuffer();
            String line;
            ((line = br.readLine()) != ) {
                sb.append(+ line);
            }
            String respone = sb.substring();
            BALog.(url + + respone);
            (callBack != ) {
                callBack.onSuccess(respone);
            }
        }

    } (SocketTimeoutException e1) {
        BALog.(url + + );
        (callBack != ) {
            callBack.onFail();
        }
        e1.printStackTrace();
    } (Exception e) {
        CrashUtil.(e);
        BALog.(url + + );
        (callBack != ) {
            callBack.onFail();
        }
        e.printStackTrace();
    } {
        {
            (activity != && !activity.isFinishing()) {
                LoadingManager.();
            }
        } (Exception e) {
        }

        {
            (os != ) {
                os.close();
            }
        } (Throwable ex) {
        }
        {
            (br != ) {
                br.close();
            }
        } (Throwable ex) {
        }
        {
            (conn != ) {
                conn.disconnect();
            }
        } (Throwable ex) {
        }
    }
}

计算机网络面试题:

即将多台计算机通过线路在网络管理协议下实现资源共享和信息传递


名词定义 
IP: 
IP层接收由更低层(网络接口层例如以太网设备驱动程序)发来的数据包 
并把该数据包发送到更高层—TCP或UDP层 
IP数据包中含有发送它的主机的地址(源地址)和接收它的主机的地址(目的地址)。

TCP: 
TCP是面向连接的通信协议,通过三次握手建立连接,通讯完成时要拆除连接(四次挥手),由于TCP是面向连接的所以只能用于端到端的通讯。

TCP将它的信息送到更高层的应用程序,例如Telnet的服务程序和客户程序。应用程序轮流将信息送回TCP层,TCP层便将它们向下传送到IP层,设备驱动程序和物理介质,最后到接收方。

 

UDP: 
UDP是面向无连接的通讯协议,UDP数据包括目的端口号和源端口号信息,由于通讯不需要连接,所以可以实现广播发送。 
UDP通讯时不需要接收方确认,属于不可靠的传输,可能会出现丢包现象,实际应用中要求程序员编程验证。

ICMP: 
ICMP与IP位于同一层,它被用来传送IP的控制信息。它主要是用来提供有关通向目的地址的路径信息


1. OSI与TCP/IP各层的结构与功能,都有哪些协议。 
OSI开放式系统互联 TCP/IP传输控制协议 
OSI模型有7层 TCP/IP模型有5层

OSI模型 
(对应TCP/IP网接口层) 
物理层:规定通信设备的机械的、电气的、功能的和过程的特性,用以建立、维护和拆除物理链路连接。 
数据链路层:传输有MAC地址的帧以及错误检测功能

==================== 
网络层:(两个主机之间)为数据包(packets)选择路由 
传输层:(两个主机的应用进程之间)提供端对端的接口=

================== 
(对应TCP/IP应用层) 
会话层:访问验证和会话管理等(如服务器验证用户登录) 
表示层:数据格式化,代码转换,数据加密等 
应用层:为操作系统或网络应用程序提供访问网络服务的接口:文件传输,电子邮件,文件服务,虚拟终端等

TCP/IP模型 
网络接口层 

网络层:(IP,ICMP) 
传输层:(TCP,UDP) 
应用层:(HTTP,FTP,DNS)

2. TCP与UDP的区别。

TCP:面向连接,从端到端和可靠的数据传递,提高IP环境下的可靠传输,流量的控制 
针对可靠性高的应用 
HTTP,DNS,FTP等协议应用到

UDP:不面向连接,不为IP提供可靠性、 流控或差错恢复功能 
适用于可靠性要求低、传输经济的应用 
DNS等协议应用到

3. TCP报文结构。 
 

4. TCP的三次握手与四次挥手过程,各个状态名称与含义,TIMEWAIT的作用。

三次握手: 
客户端发送SYN消息包请求给服务器,服务器会返回SYN+ACK确认的消息表明已经连上, 
客户端收到确认消息会再发送一个SYN+ACK报文,这样三次握手,成功后就开始分配资源建立连接

为什么不是两次握手: 
两次握手是不可靠的连接 
如果两次握手,网络延时造成的超时请求,会再次创建一个新的无效连接,并一直保持,占用资源

四次挥手: 

客户端发送中断连接请求Fin报文(表示客户端不会发送来数据了),这个时候服务端可能是处于发送数据过程中,所以服务端发送ACK报文表示自己还没准备关闭,服务端收到报文进入FIN_WAIT状态,当服务端发送数据完毕,向客户端发送一个FIN报文,表示可以断开连接,客户端再发送ACK报文,若2MSL后未响应表示服务端关闭了,客户端再关闭

自己理解:客户端断开:客户端发送Final请求报文,服务端收到final报文,发送ACK报文给服务端等待数据传输完,服务端进入Final-wait状态,服务端数据传输完成,向客户端发送Final报文,自身进入Final-wait状态 
客户端发送ACK报文确认,之后连接成功断开连接

四次的目的:防止数据未加载完就断开的情况

TIMEWAIT的作用:报文请求的有效等待时间,超过就会从网络中消失

5. 请说出HTTP协议位于TCP/IP模型中的第几层?为什么说HTTP是可靠的数据传输协议?。 
http位于TCP/IP中的应用层,因为http在传输层基于TCP协议而TCP协议是面向连接的可靠协议所以http可靠

6. HTTP和HTTPS的区别?

https是用SSL加密的。电脑与服务器之间收发的信息传输将更加安全。 
Web服务器启用SSL需要获得一个服务器证书并将该证书与要使用SSL的服务器绑定。 http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。

HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议

要比http协议安全

7. HTTP协议的结构?

请求报文:请求行 - 通用信息头 - 请求头 - 实体头 - 报文主体

响应报文:状态行 - 通用信息头 - 响应头 - 实体头 - 报文主体

7. HTTP请求的完整过程? 

Http请求的过程,与电脑上访问一个网页大概相同

  1. 建立TCP连接 
    在HTTP工作开始之前,Web浏览器首先要通过网络与Web服务器建立连接,该连接是通过TCP来完成的,该协议与IP协议共同构建Internet,即著名的TCP/IP协议族,因此Internet又被称作是TCP/IP网络。HTTP是比TCP更高层次的应用层协议,根据规则,只有低层协议建立之后才能进行更高层协议的连接,因此,首先要建立TCP连接,一般TCP连接的端口号是80。

  2. Web浏览器向Web服务器发送请求命令 
    一旦建立了TCP连接,Web浏览器就会向Web服务器发送请求命令。例如:GET/sample/hello.jsp HTTP/1.1。

  3. Web浏览器发送请求头信息 
    浏览器发送其请求命令之后,还要以头信息的形式向Web服务器发送一些别的信息,之后浏览器发送了一空白行来通知服务器,它已经结束了该头信息的发送。

  4. Web服务器应答 
    客户机向服务器发出请求后,服务器会客户机回送应答, HTTP/1.1 200 OK ,应答的第一部分是协议的版本号和应答状态码。

  5. Web服务器发送应答头信息 
    正如客户端会随同请求发送关于自身的信息一样,服务器也会随同应答向用户发送关于它自己的数据及被请求的文档。

  6. Web服务器向浏览器发送数据 
    Web服务器向浏览器发送头信息后,它会发送一个空白行来表示头信息的发送到此为结束,接着,它就以Content-Type应答头信息所描述的格式发送用户所请求的实际数据。

  7. Web服务器关闭TCP连接 
    一般情况下,一旦Web服务器向浏览器发送了请求数据,它就要关闭TCP连接,然后如果浏览器或者服务器在其头信息加入了这行代码:Connection:keep-alive 

  1. TCP连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽。

7. HTTP怎么处理长连接? 
在HTTP/1.0中,默认使用的是短连接。也就是说,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接。 
HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头有: Connection:keep-alive。Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。实现长连接要客户端和服务端都支持长连接。

8. 电脑上访问一个网页,整个过程是怎么样的? 
1)浏览器向DNS服务器请求解析该URL中的域名所对应的IP地址; 
2)解析出IP地址后,根据该IP地址和默认端口80,和服务器建立TCP连接; 
3)浏览器发出读取文件(URL中域名后面部分对应的文件)的HTTP请求,该请求报文作为TCP三次握手的第三个报文的数据发送给服务器; 
4)服务器给出相应,把对应的html文本发送给浏览器; 
5)释放TCP连接; 
6)浏览器将该文本显示出来。

9. Cookie与Session的作用于原理? 
cookie机制:客户端保持状态。“Set-Cookie”域;cookie的内容主要包括:名字,值,过期时间,路径和域。浏览器检查所有存储的cookie,如果某个cookie所声明的作用范围大于等于将要请求的资源所在的位置,则把该cookie附在请求资源的HTTP请求头上发送给服务器。

session机制:服务器端保持状态。 当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否已包含了一个session标识(称为session id),如果已包含则说明以前已经为此客户端创建过session,服务器就按照session id把这个session检索出来使用(检索不到,会新建一个);如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个session id将被在本次响应中返回给客户端保存。


 

来源: https://blog.csdn.net/mafei852213034/article/details/65939263

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值