安卓面试总结——网络

1物理层 数据链路层 网络层 传输层 应用层

2URI和URL

都定义了资源是什么,但URL还定义了该如何访问资源。URL是一种具体的URI,它是URI的一个子集,它不仅唯一标识资源,而且还提供了定位该资源的信息。URI 是一种语义上的抽象概念,可以是绝对的,也可以是相对的,而URL则必须提供足够的信息来定位,是绝对的

https://www.cnblogs.com/wojiaochuichui/p/9505096.html

tcp头部20字节,ip头部20字节

3.http、TCP/IP协议与socket之间的区别

TCP/UDP协议,基于二进制流的控制间传输协议。 TCP是面向链接的,虽然说网络的不安全不稳定特性决定了多少次握手都不能保证连接的可靠性,但TCP的三次握手在最低限度上(实际上也很大程度上保证了)保证了连接的可靠性;而UDP不是面向连接的,UDP传送数据前并不与对方建立连接,对接收到的数据也不发送确认信号,发送端不知道数据是否会正确接收,当然也不用重发,所以说UDP是无连接的、不可靠的一种数据传输协议。

HTTP协议,超文本传送协议(Hypertext Transfer Protocol ),HTTP协议是建立在TCP协议之上的一种应用。

IP协议对应于网络层,TCP协议对应于传输层,主要解决数据如何在网络中传输。而HTTP协议对应于应用层,主要用于包装数据。

Socket相当于调用接口(API),用来调取TCP/IP协议。

Socket连接过程分为三个步骤:服务器监听,客户端请求,连接确认。

1、服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。

2、客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。

3、连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。

Java中能接受其他通信实体连接请求的类是ServerSocket,ServerSocket对象用于监听来自客户端拿到Socket连接,如果没有连接,它将一直处于等待状态。

创建ServerSocket对象,绑定监听的端口;

调用accept()方法监听客户端的请求;

连接建立后,通过输入流InputStream读取接收到的数据;

通过输出流OutputStream向客户端发送响应信息;

调用close()方法关闭相关资源。

client构造器中指定远程主机时既可使用InetAddress来指定,也可直接使用String对象来指定,但程序通常使用String对象来指定远程IP地址。

创建Socket对象,指明需要连接的服务器的IP地址和端口号;

连接建立后,通过输出流OutputStream向服务器发送请求信息;

通过输入流InputStream获取服务器响应的信息;

调用close()方法关闭套接字。

http状态码

200 - 请求成功

301 - 资源(网页等)被永久转移到其它URL

404 - 请求的资源(网页等)不存在

500 - 内部服务器错误

在浏览器中输入www.baidu.com后执行的全部过程

https://www.jianshu.com/p/4cb8227cd766

1、客户端浏览器通过DNS解析到www.baidu.com的IP地址220.181.27.48,通过这个IP地址找到客户端到服务器的路径。客户端浏览器发起一个HTTP会话到220.161.27.48,然后通过TCP进行封装数据包,输入到网络层。

2、在客户端的传输层,把HTTP会话请求分成报文段,添加源和目的端口,如服务器使用80端口监听客户端的请求,客户端由系统随机选择一个端口如5000,与服务器进行交换,服务器把相应的请求返回给客户端的5000端口。然后使用IP层的IP地址查找目的端。

3、客户端的网络层不用关系应用层或者传输层的东西,主要做的是通过查找路由表确定如何到达服务器,期间可能经过多个路由器,这些都是由路由器来完成的工作,我不作过多的描述,无非就是通过查找路由表决定通过那个路径到达服务器。

4、客户端的链路层,包通过链路层发送到路由器,通过邻居协议查找给定IP地址的MAC地址,然后发送ARP请求查找目的地址,如果得到回应后就可以使用ARP的请求应答交换的IP数据包现在就可以传输了,然后发送IP数据包到达服务器的地址。

GET和POST两种基本请求方法的区别

GET把参数包含在URL中,POST通过request body传递参数。

GET在浏览器回退时是无害的,而POST会再次提交请求。

GET产生的URL地址可以被Bookmark,而POST不可以。

GET请求会被浏览器主动cache,而POST不会,除非手动设置。

GET请求只能进行url编码,而POST支持多种编码方式。

GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。

GET请求在URL中传送的参数是有长度限制的,而POST么有。

对参数的数据类型,GET只接受ASCII字符,而POST没有限制。

GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。

GET参数通过URL传递,POST放在Request body中。

HTTP的底层是TCP/IP。所以GET和POST的底层也是TCP/IP,也就是说,GET/POST都是TCP链接。GET和POST能做的事情是一样一样的

GET产生一个TCP数据包;POST产生两个TCP数据包。

还有head,OPTIONS,PUT,DELETE,TRACE。,CONNECT

长的说:

对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);

而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。

也就是说,GET只需要汽车跑一趟就把货送到了,而POST得跑两趟,第一趟,先去和服务器打个招呼“嗨,我等下要送一批货来,你们打开门迎接我”,然后再回头把货送过去。

因为POST需要两步,时间上消耗的要多一点,看起来GET比POST更有效。因此Yahoo团队有推荐用GET替换POST来优化网站性能。但这是一个坑!跳入需谨慎。为什么?

https

.HTTPS是如何保证数据的安全?

(1)客户端向服务器端发起SSL连接请求;(在此过程中依然存在数据被中间方盗取的可能,下面将会说明如何保证此过程的安全)

(2) 服务器把公钥发送给客户端,并且服务器端保存着唯一的私钥

(3)客户端用公钥对双方通信的对称秘钥进行加密,并发送给服务器端

(4)服务器利用自己唯一的私钥对客户端发来的对称秘钥进行解密,在此过程中,中间方无法对其解密(即使是客户端也无法解密,因为只有服务器端拥有唯一的私钥),这样保证了对称秘钥在收发过程中的安全,此时,服务器端和客户端拥有了一套完全相同的对称秘钥。

(5)进行数据传输,服务器和客户端双方用公有的相同的对称秘钥对数据进行加密解密,可以保证在数据收发过程中的安全,即是第三方获得数据包,也无法对其进行加密,解密和篡改。

okhttp

线程池

在OKHttp中需要一个队列来保存不同的请求

在每次请求前从线程池里检查是否有超时的连接,将超时的连接从线程池移除

清理线程由线程池管理并将线程设为守护线程

线程池的复用,遍历请求队列的请求,判断是否有相同的请求

okhttp GC

搜集所有的空闲连接并记录KeepAlive时间,如果空闲连接超过5个或者某个连接的KeepAlive时间大于五分钟,就移除KeepAlive时间最长的连接,立刻再次扫描

如果目前还空闲连接不多于5个,就返回最大KeepAlive的剩余的时间,供下次清理

如果(全部都是活跃的连接),就返回默认的keep-alive时间,也就是5分钟后再执行清理

(1)、当我们通过OkhttpClient创立一个Call,并发起同步或者异步请求时;

(2)、okhttp会通过Dispatcher对我们所有的RealCall(Call的具体实现类)进行统一管理,并通过execute()及enqueue()方法对同步或者异步请求进行解决;

(3)、execute()及enqueue()这两个方法会最终调用RealCall中的getResponseWithInterceptorChain()方法,从阻拦器链中获取返回结果;

(4)、阻拦器链中,依次通过RetryAndFollowUpInterceptor(重定向阻拦器)、BridgeInterceptor(桥接阻拦器)、CacheInterceptor(缓存阻拦器)、ConnectInterceptor(连接阻拦器)、CallServerInterceptor(网络阻拦器)对请求依次解决,与服务的建立连接后,获取返回数据,再经过上述阻拦器依次解决后,最后将结果返回给调用方。

异步请求

https://www.jianshu.com/p/3214ef86a52d

RealCall

它具备有异步和同步请求,还有取消请求的功能,它内部有一个 AsyncCall 内部类,在 Dispatcher 中分发的异步请求任务就是 AsyncCall 。这里分发的任务指的是异步任务,而不是同步任务。AsyncCall 就是用表示一个异步任务的,在 Dispatcher 内部有维护了两个队列来存储 AsyncCall,分别是readyAsyncCalls 和runningAsyncCalls它们分别表示准备要执行的 AsyncCall 队列和正在执行的 AsycnCall 队列。当然还有一个 runningSyncCalls 这个队列,但是它适用于存放 RealCall ,也就是用于存储同步请求的任务。

在 finish 中虽然同步和异步执行的方法是一样的,但是执行流程并不一样,异步任务需要通过 promoteCalls 去执行下一个异步任务,而同步请求是不需要的

OkHttp 是 Square 公司开源的针对 Java 和 Android 程序,封装的一个高性能 http 请求库,所以它的职责跟 HttpUrlConnection 是一样的,支持 spdy、http 2.0、websocket ,支持同步、异步,而且 OkHttp 又封装了线程池,封装了数据转换,封装了参数使用、错误处理等,api 使用起来更加方便。可以把它理解成是一个封装之后的类似 HttpUrlConnection 的一个东西,但是你在使用的时候仍然需要自己再做一层封装,这样才能像使用一个框架一样更加顺手

Volley是 Google 官方出的一套小而巧的异步请求库,该框架封装的扩展性很强,支持 HttpClient、HttpUrlConnection,甚至支持 OkHttp,具体方法可以看 Jake 大神的这个 Gist 文件:

而且 Volley 里面也封装了 ImageLoader ,所以如果你愿意你甚至不需要使用图片加载框架,不过这块功能没有一些专门的图片加载框架强大,对于简单的需求可以使用,对于稍复杂点的需求还是需要用到专门的图片加载框架。

Volley 也有缺陷,比如不支持 post 大数据,所以不适合上传文件。不过 Volley 设计的初衷本身也就是为频繁的、数据量小的网络请求而生!

Retrofit是 Square 公司出品的默认基于 OkHttp 封装的一套 RESTful 网络请求框架,不了解 RESTful 概念的不妨去搜索学习下,RESTful 可以说是目前流行的一套 api 设计的风格,并不是标准。Retrofit 的封装可以说是很强大,里面涉及到一堆的设计模式,你可以通过注解直接配置请求,你可以使用不同的 http 客户端,虽然默认是用 http ,可以使用不同 Json Converter 来序列化数据,同时提供对 RxJava 的支持,使用 Retrofit + OkHttp + RxJava + Dagger2 可以说是目前比较潮的一套框架,但是需要有比较高的门槛。

Volley VS OkHttp

毫无疑问 Volley 的优势在于封装的更好,而使用 OkHttp 你需要有足够的能力再进行一次封装。而 OkHttp 的优势在于性能更高,因为 OkHttp 基于 NIO 和 Okio ,所以性能上要比 Volley更快。

估计有些读者不理解 IO 和 NIO 的概念,这里姑且简单提下,这两个都是 Java 中的概念,如果我从硬盘读取数据,第一种方式就是程序一直等,数据读完后才能继续操作,这种是最简单的也叫阻塞式 IO,还有一种就是你读你的,我程序接着往下执行,等数据处理完你再来通知我,然后再处理回调。而第二种就是 NIO 的方式,非阻塞式。

所以 NIO 当然要比 IO 的性能要好了, 而 Okio 是 Square 公司基于 IO 和 NIO 基础上做的一个更简单、高效处理数据流的一个库。

理论上如果 Volley 和 OkHttp 对比的话,我更倾向于使用 Volley,因为 Volley 内部同样支持使用 OkHttp ,这点 OkHttp 的性能优势就没了,而且 Volley 本身封装的也更易用,扩展性更好些。

5. OkHttp VS Retrofit

毫无疑问,Retrofit 默认是基于 OkHttp 而做的封装,这点来说没有可比性,肯定首选 Retrofit。

6. Volley VS Retrofit

这两个库都做了非常不错的封装,但是 Retrofit 解耦的更彻底,尤其 Retrofit 2.0 出来,Jake 对之前 1.0 设计不合理的地方做了大量重构,职责更细分,而且 Retrofit 默认使用 OkHttp ,性能上也要比 Volley 占优势,再有如果你的项目如果采用了 RxJava ,那更该使用 Retrofit 。

所以说这两个库相比,Retrofit 毫无疑问更有优势,你在能掌握两个框架的前提下该优先使用 Retrofit。但是个人认为 Retrofit 门槛要比 Volley 稍高些,你要理解他的原理,各种用法,想彻底搞明白还是需要花些功夫的,如果你对它一知半解,那还是建议在商业项目使用 Volley 吧

WebSocket与HTTP的关系

相同点

1. 都是一样基于TCP的,都是可靠性传输协议。

2. 都是应用层协议。

不同点

1. WebSocket是双向通信协议,模拟Socket协议,可以双向发送或接受信息。HTTP是单向的。

2. WebSocket是需要握手进行建立连接的。

联系

WebSocket在建立握手时,数据是通过HTTP传输的。但是建立之后,在真正传输时候是不需要HTTP协议的。

Socket其实并不是一个协议,而是为了方便使用TCP或UDP而抽象出来的一层,是位于应用层和传输控制层之间的一组接口。

当两台主机通信时,必须通过Socket连接,Socket则利用TCP/IP协议建立TCP连接。TCP连接则更依靠于底层的IP协议,IP协议的连接则依赖于链路层等更低层次。

WebSocket 是一种双向通信协议,在建立连接后,WebSocket 服务器和 Browser/Client Agent 都能主动的向对方发送或接收数据,就像 Socket 一样;

WebSocket 需要类似 TCP 的客户端和服务器端通过握手连接,连接成功后才能相互通信。

什么是cookie?Session和cookie有什么区别?

Cookie是会话技术,将用户的信息保存到浏览器的对象.

区别:

(1)cookie数据存放在客户的浏览器上,session数据放在服务器上

(2)cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,如果主要考虑到安全应当使用session

(3)session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,如果主要考虑到减轻服务器性能方面,应当使用COOKIE

(4)单个cookie在客户端的限制是3K,就是说一个站点在客户端存放的COOKIE不能3K。

结论:

将登陆信息等重要信息存放为SESSION;其他信息如果需要保留,可以放在COOKIE中。

HTTP2.0和HTTP1.X相比的新特性

HTTP/2有三大特性:头部压缩、Server Push、多路复用。

多路复用

在 HTTP/2 中,有两个非常重要的概念,分别是帧(frame)和流(stream)。

帧代表着最小的数据单位,每个帧会标识出该帧属于哪个流,流也就是多个帧组成的数据流。

多路复用,就是在一个 TCP 连接中可以存在多条流。换句话说,也就是可以发送多个请求,对端可以通过帧中的标识知道属于哪个请求。通过这个技术,可以避免 HTTP 旧版本中的队头阻塞问题,极大的提高传输性能。

HTTP2支持服务器推送

服务端推送是一种在客户端请求之前发送数据的机制。当代网页使用了许多资源:HTML、样式表、脚本、图片等等。在HTTP/1.x中这些资源每一个都必须明确地请求。这可能是一个很慢的过程。浏览器从获取HTML开始,然后在它解析和评估页面的时候,增量地获取更多的资源。因为服务器必须等待浏览器做每一个请求,网络经常是空闲的和未充分使用的。

为了改善延迟,HTTP/2引入了server push,它允许服务端推送资源给浏览器,在浏览器明确地请求之前。一个服务器经常知道一个页面需要很多附加资

源,在它响应浏览器第一个请求的时候,可以开始推送这些资源。这允许服务端去完全充分地利用一个可能空闲的网络,改善页面加载时间。

http2和websocket

HTTP 2.0是通过RealConnection的startHttp2方法开启

但是目前okhttp实现长连接基本都是通过websocket的方式实现

Http2Reader与Http2Writer中都是以帧的形式(二进制)来读取或者写入数据的,这样相对字符串效率会更高,当然,我们还可以用哈夫曼算法(OkHttp支持哈夫曼算法)来对帧进行压缩,从而获得更好的性能

服务端

rabbitmq和websocket和http2

https://blog.csdn.net/qq_19004627/article/details/79802685

可以同时使用

1.websocket 是HTML5 标准的一部分,实时,全双工通信,长连接。WebSocket的服务端可以将数据推送到客户端,如实时将证券信息反馈到客户端,实时天气数据,比http请求响应模式更灵活,代替了以往一些需要轮训的业务。

2.一些消息队列都是基于AMQP协议(高级消息队列协议)的比如RabbitMQ,消息队列一般用于一些需要异步处理的服务器任务或者一些通知类的任务。

3.http2.0是基于http协议,双向通信最好还是选择AMQP

websocket更多的使用场景是需要服务端主动通知客户端的实时通讯业务。

rabbitmq适合做长连接

rabbitmq

发布者(推送消息的一端):

创建一个tcp长连接connection,连接rabbitmq的监听端口5672;

在TCP长连接下创建一个信道channel,信道可以理解为connection的一个分支;

通过信道向rabbitmq声明一个交换机exchange,设置交换机的类型,名称,是否持久化等属性;

通过信道向rabbitmq声明一个队列queue,设置队列的名称,是否持久化等参数;

通过信道向rabbitmq声明一个绑定binding,设置绑定的交换机名称,队列名称,绑定的路由键;

通过信道向rabbitmq推送一条消息,指定交换机和路由;

消费者(接收消息的一端):

从第一步到第四步和发布者做的事情是一模一样的,如果已经存在相应的exchange、queue等则跳过;

通过信道向rabbitmq声明一个订阅,订阅特定的queue,并且设置回调函数及是否确认等;

通过信道监听rabbitmq推送过来的消息;

connection

rabbitmq实现的是AMQP通信协议,其所允许的最大AMQP连接数,本质上是TCP连接数;

采用TCP长连接,自带SSL认证机制,类似https,保证数据的传输安全;

信道channel可以理解成是connection下的分支,也就是说多个channel共享一个connection

exchange

作用:交换机使用来管理分发消息的,一边接受发布者提交的消息,根据消息提供的参数选择相应的处理办法,交换机是不会存储消息的,只有转发或丢弃功能;

移动端new一个ConnectionFactory来接收推送。也可以用rabbitmq来实现断连接,但是不推荐,会消耗大量cpu

你可能感兴趣的:(安卓面试总结——网络)