TCP/IP五层协议栈

目录

TCP/IP五层协议栈

一、应用层

1、xml

2、json

3.protobuffer

总结:

二、传输层

端口号:

UDP:

TCP:

1、确认应答(保证可靠传输的核心机制)

2.超时重传

3.连接管理(TCP保证可靠性的机制之一)※


一、应用层

应用层是程序猿最常打交道的一层

其他四层,都是操作系统、驱动、硬件实现好了的。

应用层的最主要任务就是“设计并实现一个应用层协议”。

举个例子:

开发的项目是一个点外卖的软件。

在要开发的功能中有一个功能叫获取用户的历史订单,这些记录存放在数据库里,此时这样的功能,就需要涉及到前端(客户端)和后端(服务器)之间的交互~

客户端发的请求需要包括:

用户的ID;

查询的起始时间;

查询的结束时间;

显示的条数...

服务器回来的响应:

查询是否成功;

如果失败,失败的原因;

查询结果数组:数组的每个元素就包含了一些属性:

商品名、商品单价、商品数量、店铺名称、支付金额~~

形如上述这样的工作,就是在设计一个应用层协议。这部分工作,本质上就是在规划请求和响应之间要传递的信息有哪些。

但是仅仅约定了传递的信息还不够,还需要约定好一个固定的格式~

设计一个应用层协议,主要就包含两个工作:

1、明确传输的信息

2、明确数据的组织格式

以下是一些当下主流的协议的模板(数据的组织格式)

1、xml

2、json

3、protobuffer

.......

下面对上述三种主流的协议模板进行描述:

1、xml

xml属于比较年代久远的数据格式,当下虽然仍然在用,但是用的越来越少。

其基本格式如图所示:

<request>

<userid>1234</userid>    用户名

<startTime>2022-04-01</startTime>   起始时间

<endTime>2022-04-09<endTime>    结束时间

<count>10</count>    显示条数

</request>

例如上面这种格式的就是xml格式,标签名就是key,标签值就是value。通过这些标签,就可以更好的体现这个数据的可读性,尤其是哪个部分是什么意思,就非常一目了然~~

虽然xml格式提高了可读性,但是有引入了太多的辅助信息——这些标签名啥的

对于一个服务器程序来说,最贵的硬件资源是网络带宽,对于xml这种格式来说,因为要表示这些辅助信息,就导致传输相同数目的请求的时候,占用的带宽是更高的~~

如果带宽固定,相同时间能够传输的请求个数就是更少的。

因此,当下xml很少用作应用层协议的设计模板了,主要是用作一些配置文件。

xml协议模板特点:可读性好,但是运行效率不高 

2、json

json是当下最流行的一种设计应用层协议的数据格式。

其基本格式如图所示:

通过{}构成了键值对结构;一个{}中有很多个键值对;键值对之间使用逗号分割;键和值之间使用冒号分割;要求键必须是字符串类型的;值允许多种数据类型(数字、字符串、布尔、另一个json.....)

{

userid:1234,

startTime:‘2022-04-01’,

endTime:'2022-04-09',

count:10

}

注意事项:json中表示字符串,单引号或者双引号都可以;

最后一个键值对,后面可以有逗号,也可以没有;

json要求key一定是字符串,因此key这里的引号可以省略;

除非key中包含了一些特殊符号(比如像空格或者-.....)必须要加上引号。

和xml相比,json同样能保证可读性,同时又没有xml那么繁琐(占用的带宽要更少一些),但是运行效率仍不高~

json虽然传输效率比xml要高,但是仍然要多传递一些冗余信息,就是key的名字,这一点在表示数组的时候,尤为明显。

例如使用json表示响应格式:

 3.protobuffer

protobuffer是一种二进制格式的数据~~

在protobuffer的数据中,不再包含上面key的名字了,而是通过顺序以及一些特殊符号,来区分每个字段的含义。同时再通过一个IDL文件来描述这个数据格式(每个部分代表着啥意思),IDL只是起到一个辅助开发的效果,并不会真的进行传输,传输的只是二进制的纯粹的数据。

上述json的响应格式就可以简化为如下版本:

1\3\3 蛋炒饭\210\21\210\3炒面\28\21\28

通过二进制得数据重新对这里得内容进行编排,甚至可能还会进行一些数据压缩。

特点:这样做传输效率会更高,但是也会让这个数据用肉眼难以观察,调试起来就不方便了。

总结:

json的应用范围要比protobuffer更广

开发效率>运行效率

开发效率包含了开发和调试。如果线上环境出问题,如果是json,出问题的请求和响应一目了然,如果是用protobuffer,二进制的数据,肉眼无法观察,因此就得自己开发一个专门的程序来解析这个数据,分析出问题的地方。

设计应用层协议,是一件非常普遍的事情,也是一件并不复杂的事情。

传输的格式除了上述三种之外,还有一些现成的已经被设计好的,已经被广泛使用了的应用层协议。(换句话说,也不是所有的时候,都需要从零设计,很多时候,可以直接基于现成的协议,稍加修改,稍加扩充,进行这种二次开发)

二、传输层

网络知识的重难点:TCP/UDP协议

经典面试题:TCP协议

端口号:

0-65535之间的整数。

知名端口号:把0-1024这些端口号,给划分除了一些具体的作用。

很多网络服务属于非常常用、非常广泛的服务,因此为了更好的管理,就给这些服务分配一些专门的端口号。

比如80 http 服务器 ,如果是自己部署http服务器,可以把他绑定到80,也可以绑定到其他端口上。

传输层协议有很多,其中最常见的就是TCP和UDP

UDP:

UDP协议格式(报文格式):

上述这种画法实际上并不对,之所以这么画,只是为了印刷的时候排版。

真实的报文格式(一个完整的UDP数据报):

所谓的把应用层数据报封装成UDP数据报,本质上就是在应用层数据报的基础上,添加了八个字节的报头,一个字节8位。

代码中写的端口号,就会被打包成这样的UDP数据报中(在报头中体现)。

以UDP客户端为例:

报文长度:表示整个UDP数据报有多长。报文长度减去8个字节就是UDP数据载荷的长度。

此处的报文长度是2个字节,范围是0-65535,0-64k。

64k大小在线代的互联网程序中,非常捉襟见肘,这是UDP使用中一个非常致命的缺陷,无法表示一个比较大的数据报,如果确实需要传输一个大的数据。可以在应用层,针对大的数据报,进行分报(拆分成多个部分),然后再通过UDP数据报分别发送,这个时候接收方再把收到的几个数据报重新拼接成完整的数据。这是下策,下策太过于麻烦,拆包组包的代码,写起来非常复杂,要考虑的情况有很多,比如说包丢了,包的顺序错误等等等等。那上策就是将UDP改成TCP,TCP就没有这样的长度限制。

校验和:用来验证网络传输的这个数据是否是正确的。

网络上传递的数据本质是光信号和电信号,但是如果有一些磁场之类的,就有可能会导致原来的一些传递的信息发生了改变。如果遇到一个强磁场,就可能导致其中的某些高频信号变成低频,就可能导致0-》1,数据就出错了。

需要尽可能的识别出数据是不是出错了,校验和就能帮助我们发现数据中的错误。

校验和正确,不能保证数据100%就是对的,但是校验和不正确,一定认为数据是有问题的。

计算校验和的时候,也不一定单纯的就是使用“个数”,还可以使用数据内容参与运算,如果是基于数据内容得到的校验和,被识别出来的概率也是更高的。

扩展知识:描述一个网络数据的时候,用了这几个词:包,报,段,帧...

传输层的数据,通常叫做 段 “segment”;

网络层的数据,通常叫做 包/报 “packet”;

数据链路层,通常叫做帧“frame”。

TCP:

TCP协议格式(报文格式):

之前我们描述过TCP和UDP各自的特点,比如说TCP的特点就是有连接、面向字节流、全双工、可靠传输。针对上述特点,前三点都能够在代码中体现出来,但是对于可靠传输,我们可能并没有从代码中看出一二,但是可靠传输却是TCP最最核心的机制,因此我们要对此展开一系列的研究~,话不多说,淦着~~~

1、确认应答(保证可靠传输的核心机制)

关于可靠性:发送方发出去数据之后,能够知道对方有没有收到。

关键:接收方收到消息之后,给发送方返回一个应答报文(ACK),表示自己已经收到了~

通过一个例子来描述这个关于确认应答的一些细节:

以A向自己的男神B发送消息为例:

情况一:

A:男神男神,我可以约你看电影吗?

B:好啊好啊!

此时B向A回复了消息说“好啊好啊”就代表着A的消息成功传达至男神那里,并且男神答应了和她一起看电影。

上述这个确认应答存在一点小问题,如果A同时发送了多个消息给男神B呢?

下面请看情况二:

A:男神男神,我可以约你看电影吗?

B:好啊好啊~

A:男神,做我男朋友好吗?

B:不行~

针对上述这样的顺序来进行传输的话,两个问题的回应都还对得上~

但是一旦网络传输过程中出现了问题,数据接收的顺序和个人发送时的顺序恰好相反呢?先发后至的情况出现了是什么样的?

请看情况三:

A:男神男神,我可以约你看电影吗?

A:男神男神,做我男朋友好吗?

B:不行~

B:好啊好啊~

此时假设男神说的“好啊好啊”是针对女生说的看电影的应答,“不行”是针对做女生男朋友的应答,“不行”明明是后发的,但是先于“好啊好啊”传送给了A,此时A就会误认为男神不愿意和她看电影但是却愿意做她的男朋友,这样一来,引起了很大的误会~那为了避免出现这样的误会,我们能采取什么样的措施进行防患呢???

我们通常采用情况四的做法,对消息进行编号:

A:①男神男神,我可以约你看电影吗?

A:②男神男神,做我男朋友好吗?

B:针对②不行~

B:针对①好啊好啊

在男神的回应和女生的请求时,各自进行一一对应的编号,确认序号表示当前这个回复(应答报文)是针对哪个消息进行的确认应答!!!这样就可以避免出现上述情况三的误会~~~

在这里祝大家都能够追到自己喜欢的人哈~~

TCP报文里就存在32位的序号和32位的确认序号。

TCP的针对消息的序号,还有说法,并不是按照“消息条数”来进行编号的,而是按照字节来编号的。

如下图所示:

针对每个字节都分别进行了编号。

关于确认序号,请看如下描述:

2.超时重传

相当于对确认应答进行了补充,确认应答是网络一切正常的时候,通过ACK通知发送方我收到了,如果出现了丢包的情况,超过重传机制就要起到效果了。

还是以A向男神B发消息为例:

情况一:

A:男神男神,我可以约你看电影吗?

当女生发完这个消息之后,就会担心这个消息会不会发丢了,于是她就会去等男神给她的回复(ACK),如果确实发丢了,男神没有收到消息,那她肯定得不到男神的回复啊~

但是此时又会出现一种情况,男神确实收到了消息,但是男神回复的消息女生没有收到,那女生同样也没有收到男神的回复啊~~~

于是这就是第二种情况:

B:好啊好啊

男神回复的“好啊好啊”发生了丢包,换句话说,就是ACK丢了,虽然男神收到了消息,但是女生收不到ACK啊~~

此时女生就心急了呐,就寻思这是咋回事呢??是男神没收到?还是说男神的回复搞丢了??

于是女生就做了最坏的打算,女生就认为是自己的消息男神没收到,女神决定鼓起勇气再发一次~~

重发一次也不是立即重发,而是说等待足够的时间之后再进行重发,因为有可能是男神还没看到~~

好家伙,女生就等了一小时,还是没有收到男神的回复(ACK),此时女生才进行重发~~

等待的一小时就是超出了等待时间,重发就代表着进行重传~

重传也不一定能够保证100%能够收到男神的回复。正常情况下,连续丢包两次的概率是非常低的~但是也仍然存在可能性。

假设上述情况是男神回复的“好啊好啊”传丢了,此时女生触发了超时重传,就会导致男神收到两条重复的消息。

对于上述例子来说,男神收到两条重复的消息并没有什么影响,但是换个场景呢???比如说转账汇款呢??

因此TCP内部就会有一个去重的操作,从接收方收到的数据都会先放到操作系统内核的“接收缓冲区”中,接收缓冲区可以视为是一个内存空间,并且也可以视为是一个阻塞队列。收到新的数据,TCP就会根据序号来检查这个数据是否已经存在于接收缓冲区了。如果不存在,则丢弃,如果存在就会直接丢弃。这就保证了应用程序调用Socket API拿到的这个数据一定是不重复的~~~换句话说,应用程序感知不到超时重传的这个过程的!!!

扩展问题:重发的这个数据是会重新封装还是先将之前封装的报文缓存下来进行重发?

答案:重新封装。发送出去的数据,这是TCP负责发送的,调用一个Socket中的write操作,本质上就是把这个数据写到TCP的“发送缓冲区”中,由内核从发送缓冲区取数据,通过网卡传输(也就是封装的过程)当触发了超时重传的时候,内核就会再把刚才缓冲区的内容重新再进行封装重新传输,如果顺利收到了ACK,就可以把这个数据从发送缓冲区中删除。

对于上述例子和下面的描述,那我们不由得思考一个问题,那要是一直重传失败呢?

继续拿上面这个例子来进行描述:

女生A连续发送了两次消息男神都没有回复,那此时女生就很伤心呐,积极性不就受到了打击嘛,但是不甘心还想再试试呐,于是她下次等了两个小时才进行了下一次重传消息,当第三次依然收不到男神的回复的时候,女生就回去考虑是否是别的原因导致的收不到男神的回复呀,比如说加错微信或者男神手机丢了等等情况....于是女生就放弃了向男神发出邀请的消息。

上述过程说明,重传如果失败,可能还会再进行尝试,但是也不会无休止的进行重传,连续几次重传之后都没有收到ACK的话,就只能放弃了(自动的断开了TCP连接),并且再多次重传期间,重传的时间间隔会越来越大、频率越来越低~~首次传输失败的概率本身就是很小的,剩下的重传仍然失败的概率更是微乎其微,这个时候TCP基本上就不会指望重传成功了。

在此强调,操作系统具体重传几次才会自动放弃以及超时时间每次增加多少,这个可以通过自己去进行配置。

3.连接管理(TCP保证可靠性的机制之一)※

(1)如何建立连接

三次握手

客户端和服务器之间,通过三次交互,完成了建立连接的过程,“握手”是一个形象的比喻。

客户端是主动发起请求的一方,客户端先发送一个SYN同步报文段给服务器

我们先介绍SYN和ACK分别代表什么:

①如果SYN这一位为1,表示当前报文就是一个“同步报文段”,主机A和主机B之间要建立连接

②如果ACK这一位为1,表示这个报文就是一个“确认报文段”(上述确认应答报文,也是ACK为1)

 然后我们再反过头来看上面客户端——服务器这张图:

客户端请求与服务器建立连接,于是发送SYN报文段,服务器收到之后,就会回复客户端一个ACK确认报文段,告诉客户端说可以和自己建立连接,因为连接是由双方共同建立的,于是服务器也会向客户端发送一个SYN报文段,尝试与客户端建立连接,此时客户端收到确认报文段和同步报文段之后,向服务器发送ACK确认报文段表示可以建立连接。

这个过程就像表白,是一个双向奔赴的过程,双方都向对方表白,这个关系才能够确立~~

 重点:上述过程看起来是执行了四步才完成了连接的建立,不是说好的三步嘛?

中间的这两次,是一定可以合二为一的!!!每次要传输的数据,都要经过一系列的封装和分用才能完成传输,相比之下,封装一次的效率明显高于封装两次,就好比于网上一个店铺里买了两件衣服,打包成一个包裹发货肯定比打包成两个包裹更划算啊~~

关于TCP的两个比较重要的状态:

①、LISTEN:表示服务器启动成功,端口绑定成功,随时可以有客户端来建立连接。(手机开机,信号良好,随时可以有人给我打电话)

②、ESTABLISHED:表示客户端已经连接成功,随时可以进行通信了。(有人给我打电话,我姐听了,接下来就可以说话了)

面试怎么问?

三次握手有啥用?和可靠性有啥关系?

三次握手,相当于是“投石问路”,检查一下当前这个网络的情况是否满足可靠传输的基本条件。

如果网络信号很差,强行进行TCP传输,也会涉及到大量丢包。因此,可以认为三次握手其实也是在检测通信双反,发送能力和接收能力是否正常。

举个栗子:

一个男生A和他女朋友B打电话:

A:喂喂喂,宝贝儿,听得见不?

B:哥哥,我能听见,你能听见我说话嘛?

A:我能听见!

以这个例子来分析:

男生向女朋友说“听得见不”,此时就是在验证自己的麦克风和女朋友的听筒是否正常,当女朋友听到男生的声音后,她就知道了,男朋友的麦克风正常,自己的听筒正常,此时,她就需要验证自己的麦克风和男朋友的听筒是否正常,于是就说“我能听见,你能听见我说话嘛?”,此时当男生听到这句话的时候,他就可以知道,自己的听筒和麦克风正常,女朋友的麦克风和听筒也都正常,于是他就说“我能听见!”,当女生听到这句话的时候,她就可以知道自己的麦克风正常。

当女生说完的时候,男生就可以确认双方的四个设备都正常。这就意味着可以暧昧的聊天了~~(具备可靠传输的前提条件)

此时如果男生的麦克风出现了问题,说完了“宝贝儿,听得见不?”等待女朋友的回应,等了一会见女朋友没回应啊,因此就需要重传一下,尝试重传几次后,还是没有回应,这是就可以认为手机有问题了,暧昧不了了~(可靠通信的前提条件不具备了,就放弃了)

 让双方能够协商一些必要的信息:

依然还是举个例子:

我A想约女朋友B去吃饭:

A:宝贝儿,明早8点去吃早饭呗?

B:不中呐,我早上8点还没醒呢,要不10点?

A:好哒,那就10点~

TCP通信过程中,需要客户端和服务器之间,有一些共同的信息的,因此在三次握手的同时,也会相互之间交互一些必要的内容。

面试又会怎么问?

1.描述TCP三次握手的过程

直接上图就完事了~

2、为啥握手是三次?两次不行?四次不行?

两次不行,上述TCP三次握手过程中,两次的话,就意味着缺少了最后一次,即客户端向服务器发送ACK确认应答报文段,此时客户端知晓双方的发送和接收能力是完整的,但是服务器却不知道自己的发送能力是否OK,也不知道客户端的接收能力是否OK。因此,服务器对当前能否满足可靠传输,心里是没底的~这第三次交互,就是为了个服务器吃一个定心丸~

四次可以,但是没必要,上面咱们讲过了包快递的例子了,这里就不过多介绍了~

剩下的内容在下篇进行描述~此篇先到此结束~~~~

【网络相关面试问题——八股文篇(上)】相关推荐

  1. 【网络相关面试问题——八股文篇(下)】

    目录 一.网络层 1.IP协议 (一)IP协议报头 (二)地址管理 (三)路由选择 二.数据链路层 三.扩展知识:DNS 在上篇和中篇我们介绍了关于应用层和运输层的一些协议和细节,在此篇我们描述关于网 ...

  2. 网络编程实战之高级篇, 彻底解决面试C10k问题, 高并发服务器, IO多路复用, 同时监视多个IO事件

    目录 一.前言 二.IO多路复用的理解 三.IO多路复用的发展 select poll epoll ​四.C10K服务端代码 五. 总结 一.前言 网络入门篇,从操作系统的层次推开网络大门 网络入门基 ...

  3. linux一句话问答(网络无关篇+网络相关篇+程序开发篇+经典图书)

    一句话问答(网络无关篇+网络相关篇+程序开发篇+经典图书) --------------------------目录-网络无关篇-目录-------------------------- 0001 修 ...

  4. 计算机考研复试面试常问问题 计算机网络篇(上)

    计算机考研复试面试常问问题 计算机网络篇(上) 在复习过程中,我用心查阅并整理了在考研复试面试中可能问到的大部分问题,并分点整理了答案,可以直接理解背诵并加上自己的语言润色!极力推荐打印下来看,效率更 ...

  5. 网络相关篇Linux一句话精彩问答--2006/09/08更新--20060908pdf版本下载

    ----------------------------网络相关篇-------------------------- 2001 让apache的默认字符集变为中文(陈绪) vi httpd.conf ...

  6. linux中级篇--网络相关命令

    网络相关命令 Linux中常见的网络相关命令如下表所示,本书将选取其中使用较频繁的命令进行讲解. 命令 说明 格式 ifconfig 显示或设置网络设备 ifconfig [网络设备][选项]- pi ...

  7. DBMS连接不上 —— 在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误。

    "在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误.未找到或无法访问服务器.请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接. (provide ...

  8. 【面试 redis】【第十二篇】redis的相关面试问题【完结】

    redis的相关面试问题==完结,详情查看日记 ========================================== redis教程:http://www.redis.net.cn/t ...

  9. 设置好网络协议了为何网络还是不通_记一次菜鸟网络的面试经历

    我是一个不太爱折腾的人,因此在一个公司待久了,就不太会轻易跳槽.正因为如此,我在上家公司待了整整三年,在这里,认识了一群可爱的人,便更不舍得离去. 但因为公司属于传统企业,技术上并没有太大挑战,个人也 ...

最新文章

  1. python join split
  2. Java基类共同属性设置_java – 你有一个Hibernate实体的基类吗?
  3. 从零开始学习jQuery (五) 事件与事件对象
  4. CVPR2019接收结果公布了,但CVPR 2018的那些论文都怎么样了?
  5. HDOJ 4734 数位DP
  6. 【渝粤教育】 广东开放大学21秋期末考试法律文书10684k2
  7. android 删除开机动画,Android开机logo和开机动画的修改
  8. [GitHub][2014-05-13 06:00:39]JavaDsp
  9. Qt SQL 学习笔记二:qt建立数据库,创建和操纵表
  10. snmp使用默认团体名_CactiEZ 中文版snmp默认团体名
  11. Hexo及Next主题配置(最新版)
  12. 使用usb有线网卡u-boot无法ping通虚拟机
  13. 目标检测之RFB Net
  14. Redhat linux命令行连接wifi
  15. 道家王凤仪《五行语录》
  16. RuntimeError: stack expects each tensor to be equal size
  17. 对APP强制更新的思考
  18. 国行Android手机使用google全套GMS服务小结
  19. Golang神奇的2006-01-02 15:04:05
  20. 太阳直射点纬度计算公式_高中地理——每日讲1题(太阳直射点、太阳高度角、极昼、极夜)...

热门文章

  1. 无线电监测设备该如何选择
  2. pythoninstaller打包多个py 文件_Pyinstaller通过spec文件打包py程序(多个py脚本)
  3. iOS打电话、发短信、发邮件功能
  4. Vue项目上传到GitHub上
  5. win7下查看计算机ID,大师告诉你win7系统查找硬件ID的方法介绍
  6. java文件上传到云服务器,java文件上传到云服务器
  7. 将静态库编译到动态库中
  8. linux服务器 抓包命令 tcpdump
  9. e电帮app,开拓未来
  10. 在知识付费系统搭建上面遇到的坑