传输层是主机才会有的层次
传输层的功能
传输层提供进程和进程之间的逻辑通信。而网络层是提供的主机与主机之间的逻辑通信
复用和分用
复用:应用层所有的应用进程都可以通过传输层再传输到网络层
分用:传输层从网络层收到数据后交付指明的应用进程
传输层对收到的报文进行差错检测
传输层由两种协议 TCP、UDP
TCP和UDP的区别
TCP
传送数据前必须建立连接,数据传送结束后要释放连接。不提供广播或多播服务。由于TCP要提供可靠的面向连接的传输服务,因此不可避免的增加了许多开销(确认、流量控制、计时器、连接管理)
UDP
传送数据之前不需要建立连接,收到UDP报文后也不需要给出任何确认。并且UDP广泛用于组播(多播)
传输层的寻址与端口
端口
端口号长度为16bit,能表示65536个不同的端口号
端口号按范围划分
服务端使用的端口号
熟知端口号(1~1023):给TCP\IP最重要的一些应用程序
FTP (21) TELENT (23) SMTP (25) DNS (53) TFTP (69) HTTP (80) SNMP (161)
等级端口号(1024~49151):为应用程序所使用
用户端使用的端口号
49152~65535:仅在客户进程运行时才动态选择
**套接字Socket = **(主机IP地址,端口号) 套接字可以在网络中唯一标识主机中的进程
UDP
UDP只是在IP数据报之上增加了很少的功能,即复用分用和差错检测
UDP的主要特点
UDP是无连接的,减少开销和发送数据之前的时延
UDP使用最大努力交付,即不保证可靠交付
UDP没有拥塞控制,适合很多实时的应用(实时应用要求延迟小,并且允许稍微的拥塞)
UDP首部开销小,为8字节。而TCP为20字节
UDP是面向报文的,适合一次性传输少量数据的网络应用
面向报文即指应用层给UDP多长的报文UDP就照样发送不会分片。不想IP是面向分片的。UDP会把完整的报文整个当作自己的数据部分,不会修改一丁点应用层的报文。
再往下在网络层如果UDP报文过大就应该要分片了
所以应用层应该控制它的报文长度,不能太大也不能太小
UDP报文格式
每个首部字段为16比特,也就是2字节。四个首部字段一共是8字节。
源端口号是可有可无的,如果希望收到接收方的回应那么就填上。目的端口号必须有
UDP长度指的是头部加数据部分的总长度。检验和会检验首部和数据部分,有错则丢弃。
分用时,找不到对应的端口号,就丢弃报文。并给发送方发送ICMP(端口不可达)的错误报文。
TCP协议的特点
- TCP是面向连接(虚连接)的传输层协议
其实在TCP发送连接消息时是将进程的TCP消息向下封装最后由链路发送到目的主机解封装然后目的主机的进程再这样做。这样是物理连接。而我们在使用TCP时就感觉是两个进程在打CALL而没有关心其他,所以我们所简化的TCP连接就是虚连接。
- 每一条TCP连接只能有两个端点,所以每一条TCP都只能是点对点的
- TCP提供全双工通信。发送方和接受方可以同时发送和接收数据。TCP两端都设置有发送缓存(准备发送和已发送但没有收到确认的数据)和接收缓存(按序到达但尚未被应用程序读取的数据和不按序到达的数据)。
- TCP提供可靠交付的服务。无差错、不丢失、不重复、按序到达
- TCP面向字节流。TCP把应用程序交下来的数据仅仅看成是一连串的无结构的字节流(流:流入到进程或从进程流出的字节序列)
TCP报文段中包含有多个字节,每个字节都有编号
TCP握手.png
源端口和目的端口标明两个进程
序号(seq):在一个TCP连接中传送的字节流中的每一个字节都会按顺序编号,该字段填充的是本次所发送数据的第一个字节的序号(一次会发送多个字节)。32位4B
确认号(ack):期望收到下一个报文段的第一个数据字节的序号。如收到了一个报文段,这个段的最后一个字节的编号为6,那么就会发送一个确认TCP给发送方,并且这个确认TCP首部中的确认号为7。表示我6之前的都收到了,你可以从7开始发了
确认位ACK:ACK=1时确认号才有效。在连接建立后所有传送的报文段都应该把ACK置位1
同步位SYN:SYN=1时,标明是一个连接请求或连接接收报文
终止位FIN:FIN=1时,标明发送方数据已发完,要求释放连接
数据偏移:
在TCP头部中我们发现并没有首部长度字段。这个数据偏移字段就相当于首部长度。
它标识TCP报文段的数据部分起始位距离TCP开头有多远。也就是首部长度。
因为TCP有一个选项(可变字段),所以这里使用数据偏移来标识首部长度。另外有一个填充字段,如果添加选项字段后首部长度不是4的整数倍那么将会填充字节以达到4的整数倍。
偏移字段是以4B为单位的,可以看到偏移字段有4个字节,那么它的最大值为1111,也就是15。因为以4B为单位,所以他表示的首部长度就是15*4=60B
紧急位URG(urgent):URG=1时,标明此报文段有紧急数据,是最高优先级数据,应该尽快传送,不用在发送缓存里排队直接插队。它配合下面的紧急字段使用
紧急指针:URG=1时才有意义,指出了紧急报文段中紧急数据的字节数。如果紧急指针的值为20,那么这个紧急报文段的前20个字节是紧急数据。
推送位PSH(push):PSH=1时,接收方尽快交付接收应用进程,不用等接收缓存队列直接插队向上交付
复位RST:RST=1时,标明TCCP连接中出现了严重差错,必须释放连接,然后再重新建立连接
窗口(win):窗口字段占16位所以最大值就是65536个字节。如果A向B发送一个TCP报文,报文中的窗口字段的值为999,那么就是A告诉B我可以接收数据的上限为999。
校验和:和UDP检验方法一样,检验首部+数据,检验时要加上12B的伪首部,第四个字段为6.
选项:TCP数据部分最大长度MSS、窗口扩大、时间戳、选择确认等选项
TCP连接管理
TCP连接采用客户服务器的方式,主动发起连接建立的应用进程叫做客户,被动等待连接建立的应用进程叫服务器。但双发都可以发送信息给对方。
在传输数据的过程中,确认位ACK始终必须为1,因为接收方要回复一个确认号标识你发的我都收到了,你直接从下一个字节开始发吧。在三次握手中是没有数据部分的,所以他的序号是乱写的,只是为了验证连接是否可靠。
TCP三次握手
确认号为ack,确认位为ACK。序号为seq。ACK置1才能有确认号。
客户端:我想和你说话,听到了吗;
服务端:听到了听到了 你可以听到我说话吗;
客户端:可以呀 我想说我爱你啊(第三次握手可以包含数据部分)
Round 1:SYN=1 seq=x (随机)
连接请求报文SYN需要置1
客户端发送连接请求报文,这是并没有应用层数据可进行编号,所以设置一个随机的seq
Round 2:SYN=1 ACK=1 seq=y (随机) ack=x+1
此时是连接接收报文所以SYN置1
服务器端为该TCP连接分配缓存和变量,并向客户端返回确认报文段,允许链接,该报文段没有应用层数据
有确认号那么ACK必须也置1。确认号为x+1标识你发的我都收到了你直接发序号为x+1的字节就行了,客户端看到这个他就知道服务器已经收到他发送的序号了,此时连接应该是可靠的
服务端还要发送一个seq,他要知道客户端是否能收到服务端的消息
Round 3:SYN=0 ACK=1 seq=x+1 ack=y+1
客户端为该TCP连接分配缓存和变量,并向服务器端返回确认的确认,可以携带应用层数据
只有连接请求和连接接收这前两步才需要SYN置1,此时置0
因为连接或传输数据都需要用到确认号ack,所以确认位ACK始终置1 。ack表示我期待你发送y+1号的字节。服务器收到这条消息就知道它收到y号字节了,这个连接建立完成
因为第一次握手客户端发送的seq为x,所以此时客户端发送的数据的字节序号从x+1开始
TCP的连接释放
参与一条TCP连接的两个进程中的任何一个都能终止该连接,连接结束后,主机中的缓存将被释放
客户端:我不想和你说话了;
服务端:好吧 其实我还想说你是个好人。你能听到吗,#……%@;
服务端:那么就再见吧;
客户端:听到了,谢谢你。再见吧~¥...%@ 。 你听到了的话就走吧,我看着你;
如果服务端没有听到客户端的再见那么会再发一次再见吧,因为客户端还在看着它,所以客户端还能收到客户端的再见。此时客户端会再发一次再见。
客户端等待时间超过2MSL后也就转头走了,从此相忘于江湖。
这里的seq取决于客户端\服务端上次一发送的数据的最后一个字节序号,这里加一即可
Round 1:FIN=1 seq=u
客户端发送连接释放报文段,FIN置1,停止发送数据,主动关闭TCP连接
此时并不需要确认什么,所以不需要ACK
Round 2:ACK=1, seq=v, ack=u+1
服务端会送一个确认报文段,客户到服务器这个方向的连接就释放了。此时是半关闭状态,因为服务器还没想关,服务器此时还可以发送数据
ack=u+1 确认收到客户端的信息
Round 3:FIN=1 ACK=1 seq=w ack=u+1
服务器发送连接释放报文段,所以FIN置1
有ack那么ACK必须置1
seq的值为Round 2中服务器发送给客户端的数据的最后一个字节加1
ack还是u+1,因为Round 2后客户端已经不想说话了,并没有发数据
Round 4:ACK=1 seq=u+1 ack=w+1
客户端回送一个确认报文段,在等到时间等待计时器设置的2MSL(最长报文段寿命)后,连接彻底关闭
因为客户端发送的确认报文服务器有可能收不到,所以在客户端发送完确认报文后客户端还会等待2MSL时间,防止服务器没收到确认报文所以又发送了一次Round 3。重传后计时器重置
TCP可靠传输
可靠:保证接收方进程从缓存区读出的字节流与发送方发送缓存中的字节流一摸一样。
确认机制
超时重传
TCP发送方在规定时间内没有收到确认就要重传已发送的报文段
重传时间过短由于网络状况不同会造成很多不必要的重传,过长时间会浪费。
重传时间的规定:TCP采用自适应算法,动态改变重传时间RTTs(加权平均往返时间)RTT指的是一个报文段从发送到接收到确认报文的往返时间。所有的报文段的RTT组成了RTTs,每多一个算法就会加进去一个,就会更加精确的判断当前网络的最佳重传时间。
冗余ACK(冗余确认)
每当比期望序号大的失序报文段到达时,发送一个冗余ACK,指明下一个期待字节的序号
如发送方依次发送1、2、3、4、5号报文段
接收方接收到1,返回1的确认(确认号为2号报文段的第一个字节)期待收到2号报文段
接收方漏掉2号报文段接收到3,仍返回1的确认,期待收到2号报文段
接收方接收到4,仍返回1的确认,期待收到2号报文段
接收方接收到4,仍返回1的确认,期待收到2号报文段
发送方接收到3个对于报文段1的冗余ACK,那么就认为2号报文段丢失了,重传2号报文段。也叫快速重传。为什么冗余三次呢,因为在网络上难免有拥塞。
TCP流量控制
流量控制:让对方慢点~。TCP使用滑动窗口机制实现流量控制
在通信过程中,接收方根据自己接收缓存的大小,动态的调整发送方的发送窗口大小,即接收窗口rwnd(接收方设置确认报文段的窗口字段来将rwnd通知给发送方),发送方的发送窗口取接收窗口rwnd和拥塞窗口cend的最小值。
发送窗口包含有等待发送和已发送但未收到确认的报文段。
最后主机B发送给A一个零窗口让A先等等再发。如果B想让A发送数据了并发送了一个rwnd=400的报文段,但是A并没有收到,那么此时这两个就互相等吧。。。
所以TCP为每一个连接都设有一个持续的计时器,只要TCP连接的一方收到对方的零窗口通知,就启动持续计时器,到时间A就会发送一个零窗口探测报文段,来问B你怎么还没发还是丢包了,然后B就会再发一个rwnd=400的报文段。如果B又发送了一个零窗口的报文段,那么A就重置零窗口计时器再等。。。
TCP拥塞控制
出现拥塞的条件:对资源需求的总和 > 可用资源。
网络拥塞 =》 网络性能变坏 =》 网络吞吐量将随输入负荷增大而下降
拥塞控制的目的:协调网络中的所有主机,防止过多的数据注入到网络中。
拥塞控制是一种一点对多点的问题,接收方并不知道是哪一个发送方数据注入过多而造成了网络拥挤。而流量控制则是点对点的问题。
接收窗口:接收方根据接收缓存设置的值,并告知发送方,反应接收方容量
拥塞窗口:发送方根据自己估算的网络拥塞程度而设置的窗口值,反应网络当前容量
发送窗口:Min(接收窗口rwnd,拥塞窗口cwnd)