(接上文)
3.5传输层协议(TCP/UDP)
传输层的由来:网络层的ip帮我们区分子网,以太网层的mac帮我们找到主机,然后大家使用的都是应用程序,你的电脑上可能同时开启qq,暴风影音,等多个应用程序,那么我们通过ip和mac找到了一台特定的主机,如何标识这台主机上的应用程序,答案就是端口,端口即应用程序与网卡关联的编号。
传输层功能:建立端口到端口的通信 (进程到进程的通信) 补充:端口范围0-65535,0-1023为系统占用端口(2Byte)
常用端口
21/tcp FTP 文件传输协议
22/tcp SSH 安全登录、文件传送(SCP)和端口重定向
23/tcp Telnet 不安全的文本传送
25/tcp SMTP Simple Mail Transfer Protocol (E-mail)
69/udp TFTP Trivial File Transfer Protocol
79/tcp finger Finger
80/tcp HTTP 超文本传送协议 (WWW)
88/tcp Kerberos Authenticating agent
110/tcp POP3 Post Office Protocol (E-mail)
113/tcp ident old identification server system
119/tcp NNTP used for usenet newsgroups
220/tcp IMAP3
443/tcp HTTPS used for securely transferring web pages
3306 mysql
27017 mongodb
6379 redis
dhcp:67 68
dns:53
tomcat:8080
TCP(Transmission Control Protocol,传输控制协议)
是一种面向连接(连接导向)的、可靠的基于字节流的传输层通信协议。TCP将用户数据打包成报文段,它发送后启动一个定时器,另一端收到的数据进行确认、对失序的数据重新排序、丢弃重复数据。
可靠传输,TCP数据包没有长度限制,理论上可以无限长,但是为了保证网络的效率,通常TCP数据包的长度不会超过IP数据包的长度,以确保单个TCP数据包不必再分割。
以太网头 | ip 头 | tcp头 | 数据 |
udp协议:
不可靠传输,”报头”部分一共只有8个字节,总长度不超过65,535字节,正好放进一个IP数据包。
以太网头 | ip头 | udp头 | 数据 |
头格式如下(单位 bit):
- Source Port(源端口号):数据发起者的端口号,16bit。两字节
- Destination Port(目的端口号):数据接收者的端口号,16bit。两字节
- Sequence Number(顺序号码,Seq):用于在数据通信中解决网络包乱序(reordering)问题,以保证应用层接收到的数据不会因为网络上的传输问题而乱序(TCP会用这个顺序号码来拼接数据),32bit。
- Acknowledgment Number(确认号码,ack):是数据接收方期望收到发送方在下一个报文段的顺序号码(Seq),因此确认号码应当是上次已成功收到顺序号码(Seq)加1,32bit。
- Offset(TCP报文头长度):用于存储报文头中有多少个32bit(上图的一行),存储长度为4bit,最大可表示(23+22+2^1+1)32bit(15x4)=60bytes的报文头。最小取值5,532bit(5x4)=20bytes。
- Reserved(保留):6bit, 均为0
- TCP Flags(TCP标识位)每个长度均为1bit
CWR:压缩,TCP Flags值0x80。
ECE:拥塞,0x40。
URG:紧急,0x20。当URG=1时,表示报文段中有紧急数据,应尽快传送。
ACK:确认 应答标识位,0x10。当ACK = 1时,代表这是一个确认的TCP包,取值0则不是确认包。
PSH:推送,0x08。当发送端PSH=1时,接收端尽快的交付给应用进程。
RST:复位,0x04。当RST=1时,表明TCP连接中出现严重差错,必须释放连接,再重新建立连接。
SYN:(synchronization)同步 建立连接标识位,0x02。在建立连接时用来同步序号。(SYN=1, ACK=0)表示一个连接请求报文段。(SYN=1,ACK=1)表示同意建立连接。
FIN(finish):终止,0x01。当FIN=1时,表明此报文段的发送端的数据已经发送完毕,并要求释放传输连接。
相关解释
- 窗口:用来控制对方发送的数据量,通知发放已确定的发送窗口上限。
- 检验和:该字段检验的范围包括头部和数据这两部分。由发端计算和存储,并由收端进行验证
- 紧急指针:紧急指针在URG=1时才有效,它指出本报文段中的紧急数据的字节数。
- TCP选项:长度可变,最长可达40字节
三次握手(建立连接的过程,只能客户端发起):
- 客户端主动发送SYN包到服务器,并进入SYN_SEND状态,等待服务器确认(客户端SYN标识位为1,Sequence Number为J)
- 服务器收到SYN包并确认,发送SYN+ACK到客户端,服务器从LISTEN状态进入SYN_RECV状态(服务器SYN标识位为1,SequenceNumber为K, ACK应答标识位为 1,Acknowledgment Number为J+1)
- 客户端收到SYN+ACK包,发送ACK确认连接,发送完毕后客户端和服务端进入ESTABLISHED(建立)状态,完成三次握手(SYN位置为1,ACknowledgment Number为K+1)
完成三次握手之后,TCP才可以开始进行真正的数据传输
四次挥手(断开连接的过程,可以是客户端发起,也可以是服务器端发起,下面以客户端演示):
- 主机A主动发送FIN包,等待主机B确认
- 主机B收到FIN包并确认,发送ACK包到主机A
- 主机B发送FIN包到主机A,并等待主机A确认
- 主机A收到FIN包并确认,发送ACK包到主机B,并且丢弃连接,主机B收到ACK包后,丢弃连接
假设Client端发起中断连接请求,也就是发送FIN报文。Server端接到FIN报文后,意思是说"我Client端没有数据要发给你了",但是如果你还有数据没有发送完成,则不必急着关闭Socket,可以继续发送数据。所以你先发送ACK,“告诉Client端,你的请求我收到了,但是我还没准备好,请继续你等我的消息”。这个时候Client端就进入FIN_WAIT状态,继续等待Server端的FIN报文。当Server端确定数据已发送完成,则向Client端发送FIN报文,“告诉Client端,好了,我这边数据发完了,准备好关闭连接了”。Client端收到FIN报文后,"就知道可以关闭连接了,但是他还是不相信网络,怕Server端不知道要关闭,所以发送ACK后进入TIME_WAIT状态,如果Server端没有收到ACK则可以重传。“,Server端收到ACK后,“就知道可以断开连接了”。Client端等待了2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,我Client端也可以关闭连接了。Ok,TCP连接就这样关闭了!
【注意】 在TIME_WAIT状态中,如果TCP client端最后一次发送的ACK丢失了,它将重新发送。TIME_WAIT状态中所需要的时间是依赖于实现方法的。典型的值为30秒、1分钟和2分钟。等待之后连接正式关闭,并且所有的资源(包括端口号)都被释放。
【问题1】为什么连接的时候是三次握手,关闭的时候却是四次握手?
答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,“你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。
【问题2】为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
答:虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。
1、为什么需要三次握手
目的:为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。主要防止资源的浪费。
具体过程:
当客户端发出第一个连接请求报文段时并没有丢失,而是在某个网络节点出现了长时间的滞留,以至于延误了连接请求在某个时间之后才到达服务器。这应该是一个早已失效的报文段。但是服务器在收到此失效的连接请求报文段后,以为是客户端的一个新请求,于是就想客户端发出了确认报文段,同意建立连接。假设不采用三次握手,那么只要服务器发出确认后,新的连接就可以建立了。但是由于客户端没有发出建立连接的请求,因此不会管服务器的确认,也不会向服务器发送数据,但服务器却以为新的运输连接已经建立,一直在等待,所以,服务器的资源就白白浪费掉了。
1.1、如果在TCP第三次握手中的报文段丢失了会出现什么情况?
客户端会认为此连接已建立,如果客户端向服务器发送数据,服务器将以RST包响应,这样就能感知到服务器的错误了。
2、为什么要四次挥手
为了保证在最后断开的时候,客户端能够发送最后一个ACK报文段能够被服务器接收到。如果客户端在收到服务器给它的断开连接的请求之后,回应完服务器就直接断开连接的话,若服务器没有收到回应就无法进入CLOSE状态,所以客户端要等待两个最长报文段寿命的时间,以便于服务器没有收到请求之后重新发送请求。
防止“已失效的连接请求报文”出现在连接中,在释放连接的过程中会有一些无效的滞留报文,这些报文在经过2MSL的时间内就可以发送到目的地,不会滞留在网络中。这样就可以避免在下一个连接中出现上一个连接的滞留报文了。
五、总结:
数据传输动图如下:
https://img2020.cnblogs.com/blog/1036857/202004/1036857-20200415220004538-1827984001.gif
笔记:
五层协议
计算机1: 计算机2:
应用层 应用层
socket socket
传输层 段 传输层
网络层 包 网络层
数据链路层 帧 数据链路层
物理层 <===========交互机===========> 物理层
客户端软件send 服务端软件recv
操作系统 操作系统
计算机硬件<====物理介质=====>计算机硬件
ethernet头+ip头+tcp头+应用层的头+应用层数据
#一:传输层 tcp\udp=》基于端口
端口范围0-65535,0-1023为系统占用端口
ip+port=》标识全世界范围内独一无二的一个基于网络通信的应用程序
基于tcp协议通信之前:必须建立一个双向通信的链接
C-------------------->S
C<--------------------S
三次握手建立链接:
建立链接是为了传数据做准备的,三次握手即可
四次挥手断开链接
断开链接时,由于链接内有数据传输,所以必须分四次断开
tcp是可靠传输的
发送数据必须等到对方确认后才算完成,才会将自己内存中的数据清理掉,否则重传
ps:当服务端大量处于TIME_WAIT状态时意味着服务端正在经历高并发
tcp协议的半连接池:
backlog
[链接请求1,链接请求2,链接请求3,链接请求5]
#二:应用层:
可以自定义协议=》头部+数据部分
自定义协议需要注意的问题:
1、两大组成部分=头部+数据部分
头部:放对数据的描述信息
比如:数据要发给谁,数据的类型,数据的长度
数据部分:想要发的数据
2、头部的长度必须固定
因为接收端要通过头部获取所接接收数据的详细信息
http https ftp