TCP解决了任意长度消息的可靠传输,所以很多应用层协议比如http ftp等协议都是基于tcp实现的,在多数场景下能够满足应用层的需要,所以我们通常感知不到tcp协议。
计算机网络体系结构
可以看到应用层和传输层是面向用户的,实现用户功能的,同时传输层也是面向通信功能的,可见这一层是承上启下的一层。
其实网络当中的流量,绝大多是应用程序之间的通信产生的。比如访问网站的流量,看电影的流量等等。程序在电脑上面的表现为进程,其实访问网络上面的服务就是进程和进程的通信。
进程之间的通信就要使用各种各样的协议。应用层协议有时候要求网络是可靠的,客户端发送的请求必须得收到,网络其实是不可靠的,比如图片的发送被分为一个一个的数据包来传,如果链路上面传的数据包多,路由器处理不了,这个路由器就将这个数据包直接丢弃,那么接收端接收到的图片就是不完整的,这是不允许的。
这就得有一种机制来实现可靠传输,我们就可以在通信的两个计算机之间分别设置传输层协议,TCP协议就是专门为上面的应用程序通信提供可靠传输的。
网站要将网页传输给浏览器,将网页放到传输层,在传输层分段进行编号,分段之后给每个段添加IP地址,源地址目标地址,这就形成了数据包。接收端收到之后放到缓存里面,然后按照顺序读取,如果丢包了,那么接收端就得等着,发送端就得重新发送丢了的数据包。最后丢失的数据包到了才能读取连续收到的包。
数据包可能是不是同时到达的,也就是没有按照顺序到达,因为每个数据包都是独立选择路径的,接收端会等着这个迟到的数据包,等到这些迟到的数据包再开始都连续的数据包。
上面就是传输层为我们应用层提供可靠传输,这个协议就是TCP协议。
TCP 的作用
tcp之上是应用层协议,tcp之下是网络层ip协议,下面来了解tcp解决了什么问题。
在这幅图中有三个网络,一个用户客户端所在的网络,中间是广域网,第三个是企业idc内部的网络,客户端电脑上发起了一个get请求,tcp将不定长度的http请求切分为tcp认为合适的段,发送到目的的server上,在中间的任意一个节点报文都有可能被丢弃掉,而且路径也可能发生变换,tcp必须保证每个段都可以到达server,server接收到段之后,通常tcp层都是由操作系统的内核实现的,操作系统内核按照相同的顺序丢给了上面的tomcat,处理完之后生产了web页面,通过相同的路径返回给客户端。
在整个过程中,如何选择跨越不同的网络是由ip层解决的,如何构造一条消息和响应是由应用层决定的,但是消息如何可靠的发送,如何保证顺序都是tcp层决定的。
TCP协议的分层
- TCP:面向连接的、可靠的、基于字节流的传输层通信协议
- IP:根据IP地址穿越网络传送数据
面向连接是1对1才能连接,tcp协议不能像udp协议那样,一个主机像多个主机发送同一条消息,一对多是无法做到的
层层嵌套的“信封”:报文头部
在应用层构造好http get请求,在传输层,在Linux内核当中会将相应的消息拆分为许多tcp segment,segement大小由mms来定义的,网络层添加20个字节的ip头部,最后到数据链路层加上相应的头部,到了物理层,经过路由器,路由器会将数据链层和ip层头部剥离。
TCP 协议特点
TCP场景(需要多次交互,传输的数据比较大,分段传输)
TCP为应用层协议提供可靠传输,发送端按顺序发送,接收端按顺序接收,其间发送丢包、乱序,TCP负责重传和排序。下面是TCP的应用场景。
(1)客户端程序和服务端程序需要多次交互才能实现应用程序的功能。比如接收电子邮件使用的POP3和发送电子邮件的SMTP,传输文件的FTP,在传输层使用的是TCP。(客户端和服务端需要多次交互的通信)
(2)应用程序传输的文件需要分段传输,比如浏览器访问网页,网页中图片和HTML文件需要分段后发送给浏览器,或QQ传文件,在传输层也是选用TCP。 (在传输的时候可能需要一段时间,要将文件分为很多段去传,因为文件大,在传输的时候可能丢包,没有按照顺序到达,都需要实现可靠传输)
TCP协议示意图
TCP协议实现的功能
浏览器在请求网页的时候往TCP的缓存里面放入字节,一个一个字节往里面放,然后在里面分段,一部分字节分成一段,这些段都编号,加上这个首部来传,传输过程当中连续到的字节就可以从缓冲区里面来接受,对于发送端来说将网页以字节流的方式源源不断的往里面放,这边浏览器从缓存里面读取这些字节,在传输过程当中,这些乱序,丢包,这两端的应用程序是不知道的。
- TCP协议在通信之前需要建立连接,客户端向服务端发送请求建立连接,服务端收到之后回一个建立TCP的响应,在建立连接的时候协商参数,比如缓存有多大。建立连接需要三个数据包,需要三次握手。
- 建立连接三次握手再去协商参数,然后再去可靠传输。可靠传输:数据包丢了,或者没有按照顺序到达。
- 在可靠传输的时候还有流量控制的功能,比如接收方的缓存满了,那么接收方发送一个数据包告诉它慢点发,我这里处理不过来了。流量控制就是接收端告诉服务端发慢点,甚至停止发送。(就像一大堆快递在你家门口,你还没有来得及往屋里搬,这个时候就要告诉发货的发慢点,处理不过来)
- 拥塞避免就是可以感知网络的丢包情况,网络丢包严重的时候经常需要重传,一个一个发,发完了给一个确认,而不是一下子发10个然后各一个确认。如果发10个丢5个,还得重发5个,那还不如发慢点,发少量的包然后确认一次。可以看出TCP可以感知网络状态,避免网络拥塞。
传输完之后还需要释放连接,确保最后发送的数据包对方也收到了。
UDP 用户报文协议
在传输层还有一个协议是UDP协议,用户报文协议,和TCP相比其不提供可靠传输。不可靠有不可靠的好处,比较精简,快速,不需要建立连接,不需要释放连接。
(1)客户端程序和服务端程序通信,应用程序发送的数据包不需要分段。比如域名解析,DNS协议就是用传输层的UDP,客户端向DNS服务器发送一个报文解析某个网站的域名,DNS服务器将解析的结果使用一个报文返回给客户端。
(2)实时通信(延时尽量低),比如QQ或微信语音聊天,或视频聊天。这类应用,发送端和接收端需要实时交互,也就是不允许较长延迟,即便有几句话因为网络堵塞没听清,也不允许使用TCP等待丢失的报文,等待的时间太长了,就不能愉快的聊天了。(丢包了,网速不好,那么就重新说一遍,如果向TCP一样提供可靠传输,丢包了,说了一句话,丢包了重传,没有按照顺序到等一会,这样得过一段时间才能收到对方说的话,这就不是实时通信了)
(3)多播或广播通信(一对多通信。比如组播)。比如学校多媒体机房,老师的电脑屏幕需要教室的学生电脑接收屏幕,在老师的电脑安装多媒体教室服务端软件,学生电脑安装多媒体教室客户端软件,老师电脑使用多播地址或广播地址发送报文,学生电脑都能收到。这类应用在传输层使用UDP。
UDP协议有点像广播电台,发出的信号不需要下面的人给出确认,往外发就行了,丢包了也不管。