分布式通信协议-TCP

1.什么是TCP/IP协议

互联网协议(Internet ProtocolSuite)是一个网络通讯模型,以及一整个网络传输协议家族,为互联网的基础通讯架构。它常被通称为TCP/IP协议族(英语:TCP/IP Protocol Suite,或TCP/IP Protocols),简称TCP/IP。缓存

2.TCP/IP四层模型

由上到下分别为:应用层,传输层,网际层,网络接入层服务器

层级 主要协议
应用层 HTTP、FTP、Telnet、DNS、SMTP
传输层 TCP、UDP
网络层 IP、ICMP、IGMP
网络接入层 ARP、RARP

3.TCP协议

什么是TCP协议?

TCP(Transmission Control Protocol 传输控制协议)是一种面向链接的、可靠的、基于字节流的传输层通讯协议。网络

TCP的报文格式

源端口号和目的端口号:

标识数据从哪来发到哪去。架构

序号(seq)Sequence number:

为了解决乱序的问题,有了它就知道哪一个包先来,哪一个包后来。性能

确认序号(ack)Acknowledge number:

发出去的包应该有确认,这样才能保证消息的可靠性,就算没收到也应该有个回应,由于TCP做为IP的上一层协议,是没办法保证网络必定是稳定的,有可能丢包,TCP只能不断重传,直到送达,这样能够解决不丢包的问题。ui

状态位

例如:SYN表示发起链接,ACK表示回复,FIN表示结束链接,RST表示链接重置,PSH表示有 DATA数据传输。网络传输协议

SYN(synchronous创建联机)spa

ACK(acknowledgement 确认)线程

PSH(push传送)code

FIN(finish结束)

RST(reset重置)

URG(urgent紧急)

TCP的三次握手

三次握手,其实就是创建TCP链接的一个过程,这个过程须要客户端和服务端总共发送三个包来确认链接。

1)、为何要发送三个包确认链接呢,发两个或者四个不行嘛?

客户端A和服务器B通信

A:我要和你链接。单相思是没有用的,必需要B赞成。

B:好,我赞成你和我链接。这时候A不知道你赞成仍是不一样意,因此得告诉A。

A:收到B赞成的消息,创建链接。A知道B赞成了就能够直接创建链接了。

因此,创建TCP链接最少得发三个包,两个少了,4个多了,不必。

2)、三次握手过程

客户端A和服务器B进行通信

起初,客户端A、服务器B处于CLOSE状态。服务器B监听某个端口,进入LISTEN状态。

  1. 第一次握手:客户端A发送状态位SYN=1(A向B创建链接),随机产生一个seq=x给服务器B表示发起链接,以后处于SYN-SENT状态
  1. 第二次握手:服务器B接受到A的链接请求,再向A发送一个状态位ACK=1(ACK客户端的链接),SYN=1(B赞成和A链接),确认序号ack=x+1(就是收到A的包的序号seq+1),随机产生一个序号seq=y。以后进入SYN-RCVD 状态。
  1. 第三次握手:客户端A收到B的确认,检查ack是否为x+1,以及ACK是否为1,若正确,发送顺序号ack=y+1,ACK=1(ACK服务器的链接)的包给B,告诉B我已经知道你赞成和我链接了,以后客户端A进入ESTABLISHED状态,服务器B收到后确认seq值与ACK=1则链接创建成功。一样进入ESTABLISHED状态。

如图:

SYN攻击: 在三次握手过程当中,Server发送SYN-ACK以后,收到Client的ACK以前的TCP链接称为半链接(half-open connect),此时Server处于SYN_RCVD状态,当收到ACK后,Server转入ESTABLISHED状态。SYN攻击就是Client在短期内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server回复确认包,并等待Client的确认,因为源地址是不存在的,所以,Server须要不断重发直至超时,这些伪造的SYN包将产时间占用未链接队列,致使正常的SYN请求由于队列满而被丢弃,从而引发网络堵塞甚至系统瘫痪。SYN攻击时一种典型的DDOS攻击,检测SYN攻击的方式很是简单,即当Server上有大量半链接状态且源IP地址是随机的,则能够判定遭到SYN攻击了,使用以下命令可让之现行: #netstat -nap | grep SYN_RECV

TCP的四次挥手

四次挥手(Four-Way Wavehand)即终止TCP链接,就是指断开一个TCP链接时,须要客户端和服务端总共发送4个包以确认链接的断开。

假如,上面的客户端A要和服务器B要断开链接了,A不玩了,此时A和B都处于ESTABLISHED状态

第一次挥手:A和B说,我不玩了,给B发送一个FIN(结束链接)。A由ESTABLISHED变为FIN-WAIT-1状态。

第二次挥手:B收到A说不玩了的请求,因而对A说,我知道了。而后B由EStABLISHED状态进入CLOSED-WAIT状态,可是B这可能还有A上次请求的包还没发完,因此A收到B的ACK后由FIN-WAIT-1状态进入到FIN-WAIT-2状态。

第三次挥手:B已经处理完了全部要发给A的包,能够结束链接了,因而向A发送一个FIN,B而后进入LAST-ACK状态。

第四次挥手:A收到B的FIN请求,知道B能够断开链接了,接着向B发送一个ACK,而后A进入TIME-WAIT状态,等待2MSL(Maximun Segment LifeTime:最大报文生存时间)。B收到A的ACK后就进入到CLOSED状态,A等待2MSL也进入到CLOSED状态。

如图:

为何最后A要等待2MSL呢?
复制代码

一、由于A在收到B的FIN后给B发送了一个ACK,有可能B并无收到A的ACK,因此B会向A从新发送一个FIN请求,因此A要保证就算B没收到我发送的ACK,A还能在接收到B的重发的FIN。A会重发一个ACK而且足够时间到达B。

二、若是A直接跑路,A的端口就直接空出来了,可是B不知道啊,B原来向A发过的包颇有可能还在路上,若是A的端口被一个新应用占用,那么这个新应用会接受到上个链接中B发过来的包,虽然序列号是从新生成的,可是这里为了保险起见,A仍是得等待一个足够长的时间,等这些包都死翘翘,在空出端口来。

4. TCP通讯原理

首先,对于TCP通讯来讲,每一个TCP Socket的内核中都有一个发送缓冲区和一个接收缓冲区,TCP的全双工的工做模式及TCP的滑动窗口就是依赖于这两个独立的Buffer和该Buffer的填充状态。 接收缓冲区把数据缓存到内核,若应用进程一直没有调用Socket的read方法进行读取,那么该数据会一直被缓存在接收缓冲区内。无论进程是否读取Socket,对端发来的数据都会通过内核接收并缓存到Socket的内核接收缓冲区。 read索要作的工做,就是把内核接收缓冲区中的数据复制到应用层用户的Buffer里。

进程调用Socket的send发送数据的时候,通常状况下是讲数据从应用层用户的Buffer里复制到Socket的内核发送缓冲区,而后send就会在上层返回。换句话说,send返回时,数据不必定会被发送到对端。

明白了Socket读写数据的底层原理,咱们就很容易理解“阻塞模式”:对于读取Socket数据的过程而言,若是接收缓冲区为空,则调用Socket的read方法的线程会阻塞,直到有数据进入接收缓冲区;而对于写数据到Socket中的线程来讲,若是待发送的数据长度大于发送缓冲区空余长度,则会阻塞在write方法上,等待发送缓冲区的报文被发送到网络上,而后继续发送下一段数据,循环上述过程直到数据都被写入到发送缓冲区为止

从前面分析的过程来看,传统的Socket阻塞模式直接致使每一个Socket都必须绑定一个线程来操做数据,参与通讯的任意一方若是处理数据的速度较慢,会直接拖累到另外一方,致使另外一方的线程不得不浪费大量的时间在I/O等待上,因此这就是Socket阻塞模式的“缺陷”。可是这种模式在少许的TCP链接通讯的状况下,双方均可以快速的传输数据,这个时候的性能是最高的。

相关文章
相关标签/搜索