计算机与网络设备之间要实现通信的话,就必须基于相同的规则,例如中国人和中国人说话用中文,外国人和外国人说话用英文,中国人和外国人说话就必须要有相同的规则,而这个规则就是“协议”;
TCP/IP协议其实是一个协议集合,比如TCP、UDP、HTTP、IP、FTP等协议都属于TCP/IP协议;
OSI七层模型:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层;
TCP/IP协议一般划分为四层:链路层、网络层、传输层、应用层;
具体的可以看以下表格:
来自http://t.zoukankan.com/dins-p-tcp-ip.html
端口号是0~65535,一般我们使用的话端口号都要大于1023,因为1023之下的都是一些应用程序的端口号
一些协议的端口号:
TCP全称是传输控制协议(Transmission Control Protocol),是一种面向连接,可靠的,基于字节流的传输层协议
TCP的报文头是20个字节
确认序号(Ack)与控制位里面的ACK不同,Ack一般是对方上一条发送的序列号+
控制位是标识TCP每一个状态的字段,三次握手和四次挥手的关键,主要用到SYN、ACK、FIN这三个
任何基于TCP的应用,在使用之前,都要进行 “三次握手” 的连接过程,来建立连接
这里SYN可以理解为申请连接,申请的时候会置为1,ACK表示答复,只要是回复的都会置为1;当SYN为1的时候是不允许发送数据的,但是要消耗一个序列号
Ack确认序号是对已接收且按序到达的最后一个报文段的确认
1、客户端发起(第一次握手):客户端向服务器发送一个SYN包,就是用来请求连接,将SYN置为1,由于是第一次发送,所以seq是随机的a,Ack为0;
2、服务端回复(第二次握手):服务器向客户端回复一个SYN-ACK包,用来确认并接受连接请求,将SYN置为1,ACK置为1,此时的seq也是随机的b,Ack此时是a+1,则表示a+1之前的数据都收到了,一般是:对方序列号+1(连接阶段),所以 Ack=a+1;
3、客户端回复(第三次握手):客户端向服务器回复一个ACK包,用来确认服务器的回复消息,此时会将ACK置为1,seq为服务器发来的上一个Ack,即seq=a+1。
最后一步这里注意,客户端第三次确认报文段是可以携带数据的,但是如果没有携带数据的话,是不消耗序列号的,也就是说,如果这里没有携带数据的话,下一次客户端发送报文的时候,序列号(seq)还是a+1。
此图来自https://www.bilibili.com/video/BV1x441177hF?spm_id_from=333.337.search-card.all.click
传输控制块:存储TCP连接表,指向发送和接收缓存的指针,指向重传队列的指针,当前的发送和接收序号等等。
大致解释一下:
1、最初,两端的TCP进程都处于关闭(CLOSED)状态,服务器会先创建一个传输控制块,用来存储一些TCP连接过程中重要的信息,之后就准备接收TCP客户进程的连接请求,此时TCP服务器进程进入监听状态(LISTEN),等待TCP客户进程的连接请求;服务器属于被动打开连接;
2、客户进程也是首先创建传输控制块,然后在打算建立连接时向服务器发送连接请求报文段(第一次握手),并进入同步已发送状态(SYN-SENT);客户端属于主动打开连接;
3、服务器接收到连接请求后,如果同意连接,会向客户端发送连接请求确认报文段(第二次握手),并进入同步已接收状态(SYN-RCVD);
4、客户端收到连接请求确认报文段后,还会向服务器发送一个普通的确认报文段(第三次握手),并进入连接已建立状态(ESTABLISHED);服务器收到确认报文段后也进入连接已建立状态(ESTABLISHED);此时,双方已经可以进行数据传输了。
我们先了解三次握手的作用,第一次客户端发送给服务器,服务器收到之后,服务器就知道自己的接受功能是正常的,第二次服务器发送给客户端,客户端收到信息之后,客户端就会知道自己的发送功能是正常的,接受功能也是正常的,不过此时,服务器还不知道自己的发送功能是否正常,这就需要第三次握手来确认双方的收发能力都是正常的。
TCP使用序列号(seq)和确认序列号(Ack)字段来实现数据的可靠和有序传输
服务器端的序列号一直是b+1,是因为服务器发送报文段没有携带数据,所以是不消耗序列号的,所以服务器发送的报文段Seq都是b+1;
服务器的确认序列号(Ack)则是对已接收且按序到达的最后一个报文段的确认,一般是客户端上一个序列号+载荷;
流量控制:当对方发送的数据过多,自己来不及接收,就会导致信息的丢失。
流量控制是利用滑动窗口机制实现的,接收方在返回的报文中会加上自己接收窗口的大小来控制发送方的数据发送。
具体可看https://www.bilibili.com/video/BV194411h71z?spm_id_from=333.999.0.0
拥塞控制:拥塞控制就是防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载
当数据传输完成,TCP需要通过“四次挥手”机制来断开连接,释放系统资源。
1、(第一次挥手):首先客户端向服务器发送一个FIN包,也就是FIN标志位为1,用来申请断开连接;此时客户端进入终止等待1状态(FIN-WAIT-1);
2、(第二次挥手):服务器接收到客户端发来的申请断开连接的请求后会发送一个ACK确认报文,ACK标志位为1;此时服务器可能还有数据没有发送完,所以不会直接断开;服务器进入关闭等待状态(CLOSE-WAIT);
2.5、客户端在收到服务器发来的确认报文段之后,会进入终止等待2状态(FIN-WAIT-2);
3、(第三次挥手):服务器发送完数据之后,会向客户端发送一个FIN包,表示可以断开连接了,FIN标志位为1;此时服务器进入最后确认状态(LAST-ACK);
4、(第四次挥手):客户端在接收到FIN包之后,会向服务器发送一个ACK确认报文,ACK标志位为1。此时客户端进入时间等待状态(TIME-WAIT);客户端还必须要经过2*MSL时间后才会进入关闭状态(CLOSED);
4.5、服务器在收到确认报文段之后,会进入关闭状态(CLOSED);
小问题:客户端在发送完最后一个确认报文段之后,为什么不直接进入关闭状态?
答案:如果当客户端发送完最后一个确认报文段之后,直接进入关闭状态的话,此时若是发送的确认报文段丢失,而服务器接则会因为收不到客户端发来的确认报文段,服务器就会一直重传FIN包,而此时客户端已关闭,无法接收请求,服务器则会一直处于最后确认状态,无法关闭,浪费资源。
注意:FIN=1的报文段即使不携带数据,也要消耗序列号。
MSL(Maximum Segment Lifetime):意思是最长报文段寿命,RFC793建议为2分钟。 2*MSL=4分钟
分两种情况:
第一:服务器端把第二和第三次挥手合并为1次挥手
此时,如果客户端发来一个关闭连接的请求,而服务器还没有发送完数据的话,服务器就必须等待自己发送完数据之后才会向客户端发送一个FIN包,而客户端可能会因为等待时间过长以为自己的FIN包丢失而不断的重发FIN包,会导致资源浪费。
第二:客户端不进行最后一次挥手
此时若是服务器端发来的FIN包丢失的话,客户端收不到就不会进入关闭状态,依然浪费资源。
UDP(User Datagram Protocol)全称是用户数据协议,是一种无连接的、不可靠的协议;
UDP发送数据不会管对方收没收到;
1、TCP是面向连接的,而UDP是无连接的;
2、TCP是可靠的,会进行流量控制和拥塞控制,而UDP则不会进行,因此是不可靠的;
3、TCP是一对一的连接,而UDP支持一对一、一对多、多对一和多对多通信;
4、TCP是面向字节流传输,而UDP则是面向非报文传输;
5、TCP报文头较大,最少20字节,而UDP仅8字节;
6、TCP适用于要求可靠传输的应用,例如邮件传输、文件传输等场景,而UDP由于速度快,适用于实时传输,如视频会议、直播等场景。