TCP三次握手与四次挥手的过程:
1 A向B发起连接请求,此时:A---->B;
2 B收到A的发送信号,并且向A发送确认消息,此时:B---->A;
3 A收到B的确认信号,并向B发送确认信号,此时:A---->B。
<1> A向B发起请求,表示A没有数据要发送了:A——>B;
<2> B向A发送信号,确认A的断开请求:B——>A;
<3> B向A发送信号,请求断开连接,表示B没有数据要发送了:B——>A;
<4> A向B发送确认信号,同意断开:A——>B。
tcp标志位(程序程序状态寄存器):
SYN(synchronous建立联机)
ACK(acknowledgement 确认)
PSH(push传送)
FIN(finish结束)
RST(reset重置)
URG(urgent紧急)
sequence number(顺序号码)
acknowledge number(确认号码)
三次握手:
1,服务端的TCP进程首先要创建传输控制块TCB,被动的准备接受客户端进程的连接请求,然后服务端进程处于LISTEN状态,等待客户端的连接请求。 TCB(记录tcp协议运行过程中的变量,每一个TCP连接都有一个tcb。tcb结构的定义包括这个连接使用 的源端口、目的端口、目的ip、序号、应答序号、对方窗口大小、己方窗口大小、tcp状态、top输入/输出队列、应用层输出队列、tcp的重传有关变量)
2,客户端的TCP进程也要创建传输控制模块TCB,然后向服务端发出连接请求报文段,该报文段首部中的同步位SYN=1,确认号ACK=0,初始序号 seq=x。(TCP规定,SYN=1的报文段不能携带数据,但要消耗掉一个序号)此时TCP客户进程进入SYN—SENT(同步已发送)状态,这是 TCP连接的第一次握手。
3,第二次握手:服务端收到连接请求报文段后,如同意建立连接,则向客户端发送确认,在确认报文段中(SYN=1,ACK=1,确认号ack=x+1,初始序号seq=y),测试TCP服务器进程进入SYN-RCVD(同步收到)状态;
4,第三次握手:TCP客户端进程收到服务端的确认后,要向服务端给出确认报文段ACK1 ack=y+1,seq=x+1(客户端第一个报文段的seq=x,第二个报文段的seq就要+1),ACK报文段可以携带数据,不携带数据则不消耗序号。TCP连接已经建立,A进入ESTABLISHED(已建立连接)。当服务端收到客户端的确认后,也进入ESTABLISHED状态。
四次挥手:
1,客户端的应用进程先向其TCP发出连接释放报文段(FIN=1,序号seq=u)并停止再发送数据,主动关闭TCP连接,进入FIN-WAIT-1(终止等待状态),等待服务端的确认。
2,服务端收到连接释放报文段后即发出确认报文段,(ACK=1,ack=u+1,序号seq=v),服务端进入CLOSE-WAIT(关闭等待)状态,此时的TCP处于半关闭状态,客户端到服务端的连接释放。
3,客户端收到服务端的确认后,进入FIN-WAIT-2(终止等待2)状态,等待服务端发出的连接释放报文段。
4,服务端没有要向客户端发出的数据,服务端发出连接释放报文段(FIN=1,ACK=1 ack=u+1,序号seq=w),服务端进入LAST-ACK(最后确认)状态,等待客户端的确认。
5,客户端收到服务端的连接释放报文段后,对此发出确认报文段(ACK=1,seq=u+1,ack=w+1),客户端进入TIME-WAIT(时间等待)状态。此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL后,客户端才进入CLOSED状态。。
客户端TCP状态迁移:
CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
服务器TCP状态迁移:
CLOSED->LISTEN->SYN收到->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED
TCP各阶段状态详解:
LISTEN - 侦听来自远方TCP端口的连接请求;
SYN-SENT -在发送连接请求后等待匹配的连接请求;
SYN-RECEIVED - 在收到和发送一个连接请求后等待对连接请求的确认;
ESTABLISHED- 代表一个打开的连接,数据可以传送给用户;
FIN-WAIT-1 - 等待远程TCP的连接中断请求,或先前的连接中断请求的确认;
FIN-WAIT-2 - 从远程TCP等待连接中断请求;
CLOSE-WAIT - 等待从本地用户发来的连接中断请求;
CLOSING -等待远程TCP对连接中断的确认;
LAST-ACK - 等待原来发向远程TCP的连接中断请求的确认;
TIME-WAIT -等待足够的时间以确保远程TCP接收到连接中断请求的确认;
CLOSED - 没有任何连接状态;
问:为什么A还要发送一次确认呢?可以只进行二次握手吗?
答:主要为了防止已失效的连接请求报文段突然又传送到了B,因而产生错误。如A发出连接请求,但因连接请求报文丢失而未收到确认,于是A再重传一次连接请求。后来收到了确认,建立了连接。数据传输完毕后,就释放了连接,A工发出了两个连接请求报文段,其中第一个丢失,第二个到达了B,但是第一个丢失的报文段只是在某些网络结点长时间滞留了,延误到连接释放以后的某个时间才到达B,此时B误认为A又发出一次新的连接请求,于是就向A发出确认报文段,同意建立连接,不采用三次握手,只要B发出确认,就建立新的连接了,此时A不理睬B的确认且不发送数据,则B一致等待A发送数据,浪费资源。
问:Server端为何易受到SYN攻击?
答:服务器端的资源分配是在二次握手时分配的,而客户端的资源是在完成三次握手时分配的,所以服务器容易受到SYN洪泛攻击,SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server则回复确认包,并等待Client确认,由于源地址不存在,因此Server需要不断重发直至超时,这些伪造的SYN包将长时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络拥塞甚至系统瘫痪。防范SYN攻击措施:降低主机的等待时间使主机尽快的释放半连接的占用,短时间受到某IP的重复SYN则丢弃后续请求。
问:为什么A在TIME-WAIT状态必须等待2MSL的时间?
答:MSL最长报文段寿命Maximum Segment Lifetime,MSL=2
两个理由:(1)保证A发送的最后一个ACK报文段能够到达B。(2)防止“已失效的连接请求报文段”出现在本连接中。
1)这个ACK报文段有可能丢失,使得处于LAST-ACK状态的B收不到对已发送的FIN+ACK报文段的确认,B超时重传FIN+ACK报文段,而A能在2MSL时间内收到这个重传的FIN+ACK报文段,接着A重传一次确认,重新启动2MSL计时器,最后A和B都进入到CLOSED状态,若A在TIME-WAIT状态不等待一段时间,而是发送完ACK报文段后立即释放连接,则无法收到B重传的FIN+ACK报文段,所以不会再发送一次确认报文段,则B无法正常进入到CLOSED状态。(通俗的说,就是A不等B,自己直接关了,B就一直等A不会关)
2)A在发送完最后一个ACK报文段后,再经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,使下一个新的连接中不会出现这种旧的连接请求报文段。
问:为什么连接的时候是三次握手,关闭的时候却是四次握手?
答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。
问:为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
答:虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。
UDP(用户数据报协议)
(1) UDP是一个非连接的协议,传输数据之前源端和终端不建立连接,当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。在发送端,UDP传送数据的速度仅仅是受应用程序生成数据的速度、计算机的能力和传输带宽的限制;在接收端,UDP把每个消息段放在队列中,应用程序每次从队列中读一个消息段。
(2) 由于传输数据不建立连接,因此也就不需要维护连接状态,包括收发状态等,因此一台服务机可同时向多个客户机传输相同的消息。
(3) UDP信息包的标题很短,只有8个字节,相对于TCP的20个字节信息包的额外开销很小。
(4) 吞吐量不受拥挤控制算法的调节,只受应用软件生成数据的速率、传输带宽、源端和终端主机性能的限制。
(5)UDP使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的链接状态表(这里面有许多参数)。
(6)UDP是面向报文的。发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付给IP层。既不拆分,也不合并,而是保留这些报文的边界,因此,应用程序需要选择合适的报文大小。
我们经常使用“ping”命令来测试两台主机之间TCP/IP通信是否正常,其实“ping”命令的原理就是向对方主机发送UDP数据包,然后对方主机确认收到数据包,如果数据包是否到达的消息及时反馈回来,那么网络就是通的。
TCP与UDP的区别:
1.基于连接与无连接;
2.对系统资源的要求(TCP较多,UDP少);
3.UDP程序结构较简单;
4.流模式与数据报模式 ;
5.TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证。
TCP的流模式和UDP报文模式:
TCP流模式
打个比方比喻TCP,你家里有个蓄水池,你可以里面倒水,蓄水池上有个龙头,你可以通过龙头将水池里的水放出来,然后用各种各样的容器装(杯子、矿泉水瓶、锅碗瓢盆)接水。往水池里倒几次水和接几次水是没有必然联系的,也就是说你可以只倒一次水,然后分10次接完。另外,水池里的水接多少就会少多少;往里面倒多少水,就会增加多少水,但是不能超过水池的容量,多出的水会溢出。
结合TCP的概念,水池就好比接收缓存,倒水就相当于发送数据,接水就相当于读取数据。好比你通过TCP连接给另一端发送数据,你只调用了一次write,发送了100个字节,但是对方可以分10次收完,每次10个字节;你也可以调用10次write,每次10个字节,但是对方可以一次就收完。(假设数据都能到达)但是,你发送的数据量不能大于对方的接收缓存(流量控制),如果你硬是要发送过量数据,则对方的缓存满了就会把多出的数据丢弃。
这种情况是设置非阻塞I/O模型,会把内存耗尽,因为socket是存在内核中的。
UDP报文模式
UDP和TCP不同,发送端调用了几次write,接收端必须用相同次数的read读完。UPD是基于报文的,在接收的时候,每次最多只能读取一个报文,报文和报文是不会合并的,如果缓冲区小于报文长度,则多出的部分会被丢弃。也就说,如果不指定MSG_PEEK标志,每次读取操作将消耗一个报文。