网络传输总结
先说OSI七层协议
OSI七层网络模型 | TCP/IP四层概念模型 | 对应网络协议 |
---|---|---|
应用层(Application) | 应用层 | HTTP、TFTP, FTP, NFS, WAIS、SMTP |
表示层(Presentation) | Telnet, Rlogin, SNMP, Gopher | |
会话层(Session) | SMTP, DNS | |
传输层(Transport) | 传输层 | TCP, UDP |
网络层(Network) | 网络层 | IP, ICMP, ARP, RARP, AKP, UUCP |
数据链路层(Data Link) | 数据链路层 | FDDI, Ethernet, Arpanet, PDN, SLIP, PPP |
物理层(Physical) | IEEE 802.1A, IEEE 802.2到IEEE 802.11 |
在物理层,我们要解决两台物理机之间的通信需求,互相能收到比特流。以电流强弱的形式来表示传0还是1。
在数据链路层,基本保证了数据的可靠传输。
在网络层,主要是进行路由的选择与转换。
在传输层,定义了TCP协议和UDP协议,提供端到端的传输。
在会话层, 管理主机之间的会话进程 。
在表示层, 定义数据格式及加密即对上层数据或信息进行变换以保证一个主机应用层信息可以被另一个主机的应用程序理解。
在应用层,都是用户的应用程序。
三次握手
概述
我们都知道网络是通过,TCP/IP协议传输的。IP协议是无连接的通信协议,是不可靠的通信协议,它会把消息或者数据分割成较小的数据包,但是通过路由传输到目的地的过程是没有机制去检测数据的正确性和数据是否丢失。这时候就需要它的上层协议TCP来保证数据的可靠性。
TCP协议是面向连接的,可靠的,面向字节流的传输层数据结构。它是以MPU作为数据分割的最大单元,它会给每个包设置一个Sequence Number,保证数据的有序性和是否丢失,当接收端收到数据之后,会返回一个ACK。当发送端在ITT时间内没有收到ACK,就证明这个数据丢失了,会进行重传。TCP还设置了奇偶校验和函数来检验数据是否有错误,在发送和接收的时候都要校验和。
再说TCP报文首部
报文首部源端口/目的端口,Source port/Destination port是协议端口号,ip协议中的ip地址可以唯一标识一个主机,TCP协议中的协议端口,可以唯一标识一个进程。IP地址加协议加端口号可以唯一表示一个网络进程,把这种模式叫做套接字Socket.
序列号,SequeceNumber就是数据包的序号,占4个字节。
确认号,ACK就是应答序号,指的是期望下次收到的数据,如接收到的sequeceNumber为105,数据长度为200,ACK设置的值就为305.
首部长度,offset为偏移量,指的是第一个数据包距离TCP首部的位置,设置这个值的原因是因为header的数据长度是不固定的。
URG:紧急指针标志,为1表示有效,0忽略
ACK:确认序号标志,1确认号有效,0不包含确认号
PSH:push标志,为1,指当接收端收到这个程序时候应该尽快把数据发送给应用程序。而不是在缓存中排队。
RST:重置连接标志,主机奔溃或者一些原因的错误连接,或者是非法连接。
SYN:同步序列号,用来建立连接过程
FIN:finish标志,用于释放连接
Window窗口,滑动窗口,指的是发送端和接收端缓存的大小,控制发送端流量的控制
校验和 CheckSum,用来纠错,在发送端生成,在接收端进行验证。
三次握手的过程
三次握手.png三次握手采用全双工的通信方式
-
第一次握手:建立连接的时候,客户端发送SYN包到服务器,并进入SYN_SENG状态,等待服务器的确认
-
第二次握手:服务器收到SYN包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入了SYN_RECV状态。
-
第三次握手:客户端收到了服务器的SYN+ACK包,向服务器发送ACK(ack=k+1),此时包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
为什么进行三次握手
首先是为了初始化Sequence Number的初始值。当Server收到Client的SYN,回复SYN_ACK后,没收到ACK,server不断进行重试操作,直到63秒超时,计算的时间是翻倍增加,分别为2,4,8,16,32。才会断开连接。
引起的问题SYN Flood的防护措施
当有人而已攻击,恶意请求服务器导致耗尽连接队列。这时候如果SYN队列满了,通过tcp_syncookies参数回发SYN Cookie,若为正常连接则Client会回发SYN Cookie,直接建立连接。
保活机制
如果建立了连接,但是客户端忽然故障,服务端会在超时后每隔75秒发送10次保活探针报文,如果未收到响应则继续发送,尝试次数达到保活探测数量,仍然未收到,则断开连接。
四次挥手
四次挥手.png客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定FIN报文段即使不携带数据,也要消耗一个序号。
服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗
MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。
为什么关闭连接是四次握手呢?
这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的连接请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可能未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。
为什么要等2MSL后才能返回到CLOSED状态?
这是因为虽然双方都同意关闭连接了,而且握手的4个报文也都协调和发送完毕,按理可以直接回到CLOSED状态(就好比从SYN_SEND状态到ESTABLISH状态那样);但是因为我们必须要假想网络是不可靠的,你无法保证你最后发送的ACK报文会一定被对方收到,因此对方处于LAST_ACK状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT状态的作用就是用来重发可能丢失的ACK报文 。