IP协议是无连接的通讯协议不会占用两个正在通讯的计算机之间的通讯线路,这样IP就降低了对网络线路的需求,每条线可以同时满足许多不同计算机之间的通讯需要。
通过IP,消息或者其他数据会被分割为较小的独立的包并通过因特网在计算机之间传送。
IP负责将每个包路由到目的地,但是IP协议没用做任何工作去确认数据是否按顺序发送或者包是否被破坏,所以IP数据包是不可靠的,因此需要它的上层传输层TCP协议来做控制!
TCP(Transmission Control Protocol 传输控制协议):
- 面向连接的、可靠的、基于字节流的传输层通信协议
- 将应用层的数据流分割成报文段(报文段长度受MTU影响)并发送给目标节点的TCP层
- 数据包都有序号,对方收到则发送ACK(确认字符)确认,未收到则重传
- 使用校验和来检验数据在传输过程中是否有误
报文头介绍
源端口标识发起通信的那个进程,目的端口标识接受通信的那个进程。
有了端口号,接受到报文后才能够知道将报文发送到哪个进程。
在TCP传输中,每一个字节都是有序号的,从0开始。通过序号的方式保存数据的顺序,接收端接受到之后进行重新排列成为需要的数据。
因此,我对于SEQ和ACK的了解就是:
- seq(Sequence Nubmer) 代表:发送的这个包中第一个字节(如果有payload的话)的序号
- ack(Acknowledgement) 代表:已成功接受序列号到 ack-1 的数据,期望接收的下一个字节的序号为 ack
- 首部长度(Data Offset):表示TCP报文首部信息的长度。由于首部可能含有选项内容,因为TCP首部的长度是不确定的。首部长度指示了数据区在报文段中的起始偏移值。没有任何选项字段的TCP头部长度为20字节,做多可以有60字节的TCP头部。
- 保留(Reserved):6位保留字段,值通常为0;
TCP Flags标志位(每个标志位表示一个控制功能)
(1) URG:紧急指针(为0无效忽略,为1有效)
(2) ACK:确认序号(为0表示报文中不含确认信息忽略确认号字段,为1表示确认号有效)
(3) PSH:(为1表示带有PAH数据让接收方应该尽快将这个报文段交给应用层,不在缓冲区排队)
(4) RST:重建连接。(用于重置由于主机崩溃或其他原因出现错误的链接或用于拒绝非法报文段和非法请求)
(5) SYN:同步序列号,用于建立连接过程
(6) FIN:finsh标志,用于释放连接。为1时表示发送方已经没有数据发送了
- window指滑动窗口大小,用来告知发送端目的接收端的缓存大小以此来控制发送端发送数据的速率以此达到流量控制的效果
- CheckSum 校验和:奇偶校验。对整个TCP报文段,即TCP头部和TCP数据进行校验和计算以16位进行计算所得,由发送端计算和存储,并由接收端进行验证
- 紧急指针(Urgent Pointer):只有TCPFlags中URG=1时有效,如果TCP通信中,一方有紧急的数据需要尽快发送给接收方,并且让接收方的TCP协议尽快通知相应的应用程序,可以将URG置位,并通过紧急指针指示紧急数据在报文段中的结束位置。占16比特。它是一个偏移量,和序号字段中的值相加表示紧急数据最后一个字节的序号。
- Options可定义一些其他参数
TCP的三次握手流程
这里每次传递seq ack+1的原因是每次一个报文传送告知,都要消耗一个序号。
书面解释,专业回答```在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。
- 第一次握手:建立连接时,客户端发送SYN包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
- 第二次握手:服务器收到SYN包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k) 即SYN+ACK包,此时服务器进入SYN_RECV状态;
- 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1],此包发送完毕 客户端和服务器进入ESTABLISHED状态,完成三次握手。
三次握手模拟,只限理解,专业回答看上面:
两者建立链接的过程类似于彼此确认彼此能否正确的收到信息(类似于相互在进行一次小型的通讯)```AB在一个很高的楼层想尝试带彼此东西上楼,于是要尝试能不能收到彼此的东西:
- 第一次握手,SYN=1,A告诉B,老子要给你送东西了,seq=X,你在x楼等包裹;
- 第二次握手,ACK=1,老子听到了你说啥了,SYN=1,B告诉A,老子愿意收,我这就去x楼等你,ack=x+1,我在在x楼了,下一次x+1楼,seq=y,我把你的重新给你我再给你我自己的东西你试试能不能收到,你到y楼等我);
- 第三次握手,ACK=1,我收到我发的包和你发的包了,没问题,seq=x+1,你下次去的楼是x+1楼,sck=y+1,老子到y楼了,下一层y+1楼;```哈哈哈除了我大概别人也难看懂
为什么需要三次握手才能建立链接???
为了初始化Sequence Number的初始值,其实就是上面的x和y,通讯双方要告诉彼此自己的Sequence Number这个号要作为以后数据通讯的序号,以保证应用层接收到的数据接收到的数据不会因为网络上的问题而产生问题,即TCP会用这个序号来拼接数据,因此服务器端收到客户端的Sequence Number要发送一个确认报文,告诉客户端,我已收到你的Sequence Number;
首次握手的隐患-SYN超时
问题原因:
- Server收到Client的SYN,回复SYN-ACK的时候未收到ACK确认(比如IP地址是伪造的,服务器找不到)
- Server不断重试直至超时,Linux默认等待63秒才断开连接(重试5次,间隔时间翻倍1,2,4,8,16,32)
后果
可能服务器收到SYN Flood的风险,每一次这样的链接会让服务器等待63秒,如果有很多这样的请求,导致服务器打开了大量的SYNC_RECV半连接,就会把TCP的连接队列耗尽,最后导致TCP无法对其他TCP连接进行响应。
针对SYN Flood的预防措施
- SYN队列满后,TCP通过源地址端口目标地址端口和时间戳打造出一个tcp_syncookies(可看作Sequence Numbe)参数回发SYN Cookie
- 若为正常连接则Client会回发SYN Cookie,直接建立连接(即使服务器队列满了也可以)
若建立连接后Client出现故障怎么办?
TCP设有保活机制:
- 若一段时间内(保活时间)若连接处于非活动状态,开启保活功能的一段向对方发送保活探测报文,如果未收到响应则继续发送
- 尝试次数达到保活探测数仍未收到响应(这时可以确认对方主机为不可达)则中断连接