分布式通讯协议-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只能不断重传,直到送达,这样可以解决不丢包的问题。

状态位

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

SYN(synchronous建立联机)

ACK(acknowledgement 确认)

PSH(push传送)

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呢?
复制代码

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

2、如果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连接通信的情况下,双方都可以快速的传输数据,这个时候的性能是最高的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值