Android 网络基本知识

Android网络编程知识是Android开发过程中必不可少的内容,在网络开发的过程中,我们通常会用到像Volley、OkHttp、Retrofit这些高度封装好的框架,这使得我们的开发很便利但也屏蔽了相关的技术细节。而作为想要进一步的开发者来说,我们不但要会用,有时候更要理解其实现的原理,理解了后更能促进我们更好的使用这些框架。Ok,这篇文章我们讲一讲网络的基本知识。

OSI 七层网络模型

为了使不同的厂家生产的计算机能够通信,以便能在更大的范围内建立计算机网络,国际标准化组织(ISO)在 1978 年提出了“开放系统互联参考模型”,即 OSI/RM 模型(Open System Interconnection/Reference Model)。他将计算机网络体系结构的通信协议划分为了七层,自下而上依次分别是:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。其中低四层完成数据传输,高三层面向用户。

物理层
物理层(Physical Layer)在局部局域网上传送数据帧(data frame),它负责管理计算机通信设备和网络媒体之间的互通。包括了针脚、电压、线缆规范、集线器、中继器、网卡、主机适配器等。
数据链路层
数据链路层(Data Link Layer)负责网络寻址、错误侦测和改错。当表头和表尾被加至数据包时,会形成帧。数据链表头(DLH)是包含了物理地址和错误侦测及改错的方法。数据链表尾(DLT)是一串指示数据包末端的字符串。例如以太网、无线局域网(Wi-Fi)和通用分组无线服务(GPRS)等。
分为两个子层:逻辑链路控制(logic link control,LLC)子层和介质访问控制(media access control,MAC)子层。
网络层
网络层(Network Layer) 决定数据的路径选择和转寄,将网络表头(NH)加至数据包,以形成分组。网络表头包含了网络数据。例如:互联网协议(IP)等。
传输层
传输层(Transport Layer)把传输表头(TH)加至数据以形成数据包。传输表头包含了所使用的协议等发送信息。例如:传输控制协议(TCP)等。
会话层
会话层(Session Layer)负责在数据传输中设置和维护计算机网络中两台计算机之间的通信连接。
表达层
表达层(Presentation Layer)把数据转换为能与接收者的系统格式兼容并适合传输的格式。
应用层
应用层(Application Layer)提供为应用软件而设的接口,以设置与另一应用软件之间的通信。例如: HTTP,HTTPS,FTP,TELNET,SSH,SMTP,POP3等。

TCP/IP 四层模型

由于 OSI/RM 模型过于复杂难以实现,现实中广泛使用的是 TCP/IP 模型。TCP/IP 是一个协议集,是由 ARPA ( Advanced Research Projects Agency Network 高等研究计划署网络 ) 于 1977 到 1979 年推出的一种网络体系结构和协议规范。随着 Internet 的发展,TCP/IP 得到进一步的研究和推广,成为 Internet 上的 “通用模型”。
  TCP/IP 模型在 OSI 模型的基础上进行了简化,去掉了OSI参考模型中的会话层和表示层(这两层的功能被合并到应用层实现),同时将OSI参考模型中的数据链路层和物理层合并为主机到网络层。变成了四层,从下到上分别为:网络接口层、网络层、传输层、应用层。与 OSI 体系结构对比如下:


TCP/IP模型与OSI体系结构比较.png

IP 协议

网际协议((英语:Internet Protocol,缩写为IP),又译互联网协议,是用于分组交换数据网络的一种协议。
  IP是在TCP/IP协议族中网络层的主要协议,任务仅仅是根据源主机和目的主机的地址来传送数据。为此目的,IP定义了寻址方法和数据报的封装结构。第一个架构的主要版本,现在称为IPv4,仍然是最主要的互联网协议,尽管世界各地正在积极部署IPv6。IP协议的作用在于把各种数据包准确无误的传递给对方,其中两个重要的条件是IP地址和MAC地址(Media Access Control Address)。由于IP地址是稀有资源,不可能每个人都拥有一个IP地址,所以我们通常的IP地址是路由器给我们生成的IP地址,路由器里面会记录我们的MAC地址。而MAC地址是全球唯一的,除去人为因素外不可能重复。举一个现实生活中的例子,IP地址就如同是我们居住小区的地址,而MAC地址就是我们住的那栋楼那个房间那个人。

TCP 协议

传输控制协议(英语:Transmission Control Protocol,缩写为TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
TCP 协议被认为是稳定的协议,因为它有以下特点:

  • 面向连接,“三次握手”
  • 双向通信
  • 保证数据按序发送,按序到达
  • 超时重传
     要使用 TCP 传输数据,必须先建立连接,传输完成后释放连接。分别对应常说的“三次握手”、“四次挥手”。

TCP 的三次握手与四次挥手

三次握手与四次分手的流程如下所示:


image

三次握手

  • 第一次握手:建立连接。客户端发送连接请求报文段,将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_RCVD状态;
  • 第三次握手:客户端收到服务器的SYN+ACK报文段。然后将ACK设置为y+1,向服务器发送ACK报文段,这个报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED状态,完成TCP三次握手。
      当客户端和服务器通过三次握手建立了TCP连接后,当数据传输完毕,断开连接时就需要进行TCP的四次挥手。

四次挥手

TCP 协议中,在通信结束后,需要断开连接,这需要通过四次挥手,客户端或服务器均可主动发起,主动的一方先断开,这里以客户端先断开为例:

  • 第一次分手:客户端设置Seq和ACK,向服务器端发送一个FIN报文段;此时,客户端进入FIN_WAIT_1状态;客户端表示没有数据要发送给服务器端了;
  • 第二次分手:服务器端收到了客户端发送的FIN报文段,向主机1回一个ACK报文段,ACK为Sequence Number加1;客户端进入FIN_WAIT_2状态;服务器告诉客户端,我“同意”你的关闭请求;
  • 第三次分手:服务器向客户端发送FIN报文段,请求关闭连接,同时服务器进入LAST_ACK状态;服务器告诉客户端,我也没啥数据要发给你了,请求断开。
  • 第四次分手:客户端收到服务器发送的FIN报文段,向服务器发送ACK报文段,然后客户端进入TIME_WAIT状态;服务器收到客户端的ACK报文段以后,就关闭连接;此时,客户端等待2MSL后依然没有收到回复,则证明服务端已正常关闭,那好,客户端也可以关闭连接了。

为什么要进行三次握手

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

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

为什么要进行四次挥手

TCP 连接是全双工的,每一端都可以同时发送和接受数据,关闭的时候两端都要关闭各自两个方向的通道,总共相当于要关闭四个。

以客户端发起关闭为例
1.服务器读通道关闭
​2.客户端写通道关闭
​3.客户端读通道关闭
​4.服务器写通道关闭

客户端为什么要等待 2MSL?

MSL(Maximum Segment Life),是 TCP 对 TCP Segment 生存时间的限制

客户端在发出确认服务端关闭的 ACK 后,它没有办法知道对方是否收到这个消息,于是需要等待一段时间,如果服务端没有收到关闭的消息后会重新发出 FIN 报文,这样客户端就知道自己上条消息丢了,需要再发一次;如果等待的这段时间没有在收到 FIN 的重发报文,说明它的确已经收到断开的消息并且已经断开了。
  这个等待时间至少是:客户端的 timeout + FIN 的传输时间,为了保证可靠,采用更加保守的等待时间 2MSL。

UDP协议

用户数据报协议(英语:User Datagram Protocol,缩写为UDP),又称用户数据报文协议,是一个简单的面向数据报的传输层协议。

UDP是一个不可靠的或者说无连接的协议,他有以下的特点:
UDP 缺乏可靠性。UDP 本身不提供确认,序列号,超时重传等机制。UDP 数据报可能在网络中被复制,被重新排序。即 UDP 不保证数据报会到达其最终目的地,也不保证各个数据报的先后顺序,也不保证每个数据报只到达一次
UDP 数据报是有长度的。每个 UDP 数据报都有长度,如果一个数据报正确地到达目的地,那么该数据报的长度将随数据一起传递给接收方。而 TCP 是一个字节流协议,没有任何(协议上的)记录边界。
UDP 是无连接的。UDP 客户和服务器之前不必存在长期的关系。UDP 发送数据报之前也不需要经过握手创建连接的过程。
UDP 支持多播和广播。
  UDP 协议没有 TCP 协议稳定,因为它不建立连接,也不按顺序发送,可能会出现丢包现象,使传输的数据出错。但是有得就有失,UDP 的效率更高,因为 UDP 头包含很少的字节,比 TCP 负载消耗少,同时也可以实现双向通信,不管消息送达的准确率,只负责无脑发送。UDP 服务于很多知名应用层协议,比如 NFS(网络文件系统)、SNMP(简单网络管理协议)。UDP 一般多用于 IP 电话、网络视频等容错率强的场景。

Socket (套接字)

[图片上传失败...(image-efc77a-1558278902009)]
  Socket 作为应用层和传输层之间的桥梁,与之关系最大的两个协议就是传输层中的 TCP 和 UDP协议。
  Socket 是对 TCP/IP 协议族的一种封装,是应用层与TCP/IP协议族通信的中间软件抽象层。TCP或者UDP的报文中,除了数据本身还包含了包的信息,比如目的地址和端口,包的源地址和端口,以及其他附加校验信息。从设计模式的角度看来,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
  Socket 还可以认为是一种网络间不同计算机上的进程通信的一种方法,利用三元组(ip地址,协议,端口)就可以唯一标识网络中的进程,网络中的进程通信可以利用这个标志与其它进程进行交互。
  Socket 起源于 Unix ,Unix/Linux 基本哲学之一就是“一切皆文件”,都可以用“打开(open) –> 读写(write/read) –> 关闭(close)”模式来进行操作。因此 Socket 也被处理为一种特殊的文件。


image

如图所示,Socket 被称为“套接字”,它把复杂的 TCP/IP 协议簇隐藏在背后,为用户提供简单的客户端到服务端接口,让我们感觉这边输入数据,那边就直接收到了数据,像一个“管道”一样。

Socket 的使用

Socket 的基本操作有以下几部分:

  1. 连接远程机器
  2. 发送数据
  3. 接收数据
  4. 关闭连接
  5. 绑定端口
  6. 监听到达数据
  7. 在绑定的端口上接受来自远程机器的连接

要实现客户端与服务端的通信,双方都需要实例化一个 Socket。
在 Java 中,客户端可以实现上面的 1、2、3、4、,服务端实现 5、6、7.
Java.net 中为我们提供了使用 TCP、UDP 通信的两种 Socket:
ServerSocket:流套接字,TCP
DatagramSocket:数据报套接字,UDP

使用 TCP 通信的 Socket 流程

服务端

  1. 调用 ServerSocket(int port) 创建一个 ServerSocket,绑定到指定端口
  2. 调用 accept() 监听连接请求,如果客户端请求连接则接受,返回通信套接字
  3. 调用 Socket 类的 getOutputStream() 和 getInputStream() 获取输出和输入流,进行网络数据的收发
  4. 关闭套接字

客户端:

  1. 调用 Socket() 创建一个流套接字,连接到服务端
  2. 调用 Socket 类的 getOutputStream() 和 getInputStream() 获取输出和输入流,进行网络数据的收发
  3. 关闭套接字

使用 UDP 通信的 Socket 流程

服务端:

  1. 调用 DatagramSocket(int port) 创建一个数据报套接字,绑定到指定端口
  2. 调用 DatagramPacket(byte[] buf, int length) 建立一个字节数组,以接受 UDP 包
  3. 调用 DatagramSocket 的 receive() 接收 UDP 包
  4. 调用 DatagramSocket.send() 发送 UDP 包
  5. 关闭数据报套接字

客户端:

  1. 调用 DatagramSocket() 创建一个数据报套接字
  2. 调用 DatagramPacket(byte buf[], int offset, int length,InetAddress address, int port) 建立要发送的 UDP 包
  3. 调用 DatagramSocket 的 receive() 接收 UDP 包
  4. 调用 DatagramSocket.send() 发送 UDP 包
  5. 关闭数据报套接字
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容

  • 运输层协议概述 从通信和信息处理的角度看,运输层向它上面的应用层提供通信服务,它属于面向通信部分的最高层,同时也是...
    srtianxia阅读 2,387评论 0 2
  • 个人认为,Goodboy1881先生的TCP /IP 协议详解学习博客系列博客是一部非常精彩的学习笔记,这虽然只是...
    贰零壹柒_fc10阅读 5,050评论 0 8
  • 网络编程 一.楔子 你现在已经学会了写python代码,假如你写了两个python文件a.py和b.py,分别去运...
    go以恒阅读 1,982评论 0 6
  • 1.TCP报头格式 UDP报头格式 TCP报头格式 UDP报头格式 具体的各部分解释看 TCP报文格式详解 - ...
    杰伦哎呦哎呦阅读 2,425评论 0 5
  • 网络编程的概述 网络编程的实质就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换。 一.OSI网络模型...
    思念挥霍阅读 369评论 0 0