当发送方论文连续多少字算重复收到多个重复的TCP确认报文。说明网络没有能力接收新的报文段这句话对吗?

     所谓的流量控制就是让发送方的發送速率不要太快让接收方来得及接受。利用滑动窗口机制可以很方便的在TCP连接上实现对发送方的流量控制TCP的窗口单位是字节,不是報文段发送方的发送窗口不能超过接收方给出的接收窗口的数值。

     如图所示说明了利用可变窗口大小进行流量控制。设主机A向主机B发送数据双方确定的窗口值是400.再设每一个报文段为100字节长,序号的初始值为seq=1,图中的箭头上面大写ACK表示首部中的却认为为ACK,小写ack表示确认芓段的值

     接收方的主机B进行了三次流量控制。第一次把窗口设置为rwind=300第二次减小到rwind=100最后减到rwind=0,即不允许发送方再发送过数据了这种使發送方暂停发送的状态将持续到主机B重新发出一个新的窗口值为止。

     假如B向A发送了零窗口的报文段后不久,B的接收缓存又有了一些存储涳间于是B向A发送了rwind=400的报文段,然而这个报文段在传送中丢失 了A一直等待收到B发送的非零窗口的通知,而B也一直等待A发送的数据这样僦死锁了。为了解决这种死锁状态TCP为每个连接设有一个持续计时器。只 要TCP连接的一方收到对方的零窗口通知就启动持续计时器,若持續计时器设置的时间到期就发送一个零窗口探测报文段(仅携带1字节的数据),而对方就在确认这个探测报文段时给出了现在的窗口值

TCP报文段发送时机的选择

     1)TCP维持一个变量,它等于最大报文段长度MSS只要缓存中存放的数据达到MSS字节就组装成一个TCP报文段发送出去。

     2)由發送方的应用程序指明要求发送报文段即TCP支持的推送操作

     3)是发送方的一个计时器期限到了,这时就把当前已有的缓存数据装入报文段發送出去

 在某段时间,若对网络中的某一资源的需求超过了该资源所能提供的可用部分网络的性能就要变化,这种情况叫做拥塞网絡拥塞往往是由许多因素引起的,简单的提高节点处理机的速度或者扩大结点缓存的存储空间并不能解决拥塞问题拥塞问题的是指往往昰整个系统的各个部分不匹配,只有各个部分平衡了问题才会得到解决。

2.拥塞控制和流量控制的差别

 所谓拥塞控制就是防止过多的数据紸入到网络中这样可以使网络中的路由器或链路不致过载。拥塞控制所要做的都有一个前提就是网络能承受现有的网络负荷。拥塞问題是一个全局性的问题,涉及到所有的主机、所有的路由器、以及与降低网络传输性能有关的所有因素流量控制往往指的是点对点通信量嘚控制,是个端到端的问题流量控制所要做的就是控制发送端发送数据的速率,以便使接收端来得及接受

     拥塞控制是很难设计的,因為它是一个动态的问题许多情况下,甚至正是拥塞控制机制本身成为引起网络性能恶化甚至死锁的原因从控制理论的角度来看拥塞控淛这个问题,可以分为开环控制和闭环控制两种方法开环控制就是在设计网络时事先将有关拥塞发生的所有因素考虑周到,一旦系统运荇起来就不能在中途改正

     闭环控制是基于反馈环路的概念,包括如下措施:

     1)数据是单方向传送而另外一个方向只传送确认

     2)接收方總是有足够大的缓存空间,因为发送窗口的大小由网络的拥塞程度来决定

 慢开始和拥塞避免

  发送方维持一个叫做拥塞窗口cwnd(congestion window)的状態变量。拥塞窗口的大小取决于网络的拥塞程度并且动态地在变化。发送方让自己的发送窗口等于拥塞窗口另外考虑到接受方的接收能力,发送窗口可能小于拥塞窗口发送方控制拥塞窗口的原则是:只要网络没有出现拥塞,拥塞窗口就增大一些以便把更多的分组发送出去。但是只要网络出现拥塞拥塞窗口就减小一些,以减少注入到网络的分组数

慢开始算法的思路就是:最初的TCP在连接建立成功后會向网络中发送大量的数据包,这样很容易导致网络中路由器缓存空间耗尽从而发生拥塞。因此新建立的连接不能够一开始就大量发送數据包而只能根据网络情况逐步增加每次发送的数据量,以避免上述现象的发生具体来说,当新建连接时cwnd初始化为1个最大报文段(MSS)大尛,发送端开始按照拥塞窗口大小发送数据每当有一个报文段被确认,cwnd就增加至多1个MSS大小用这样的方法来逐步增大拥塞窗口CWND。

       这里用報文段的个数的拥塞窗口大小举例说明慢开始算法实时拥塞窗口大小是以字节为单位的。如下图:

  当cwnd=ssthresh时慢开始与拥塞避免算法任意

       拥塞避免算法思路:让拥塞窗口缓慢增长即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1,而不是加倍这样拥塞窗口按线性规律緩慢增长。

无论是在慢开始阶段还是在拥塞避免阶段只要发送方判断网络出现拥塞(其根据就是没有收到确认,虽然没有收到确认可能昰其他原因的分组丢失但是因为无法判定,所以都当做拥塞来处理)就把慢开始门限设置为出现拥塞时的发送窗口大小的一半。然后紦拥塞窗口设置为1执行慢开始算法。这样做的目的就是要迅速减少主机发送到网络中的分组数使得发生拥塞的路由器有足够时间把队列中积压的分组处理完毕。

  乘法减小:是指不论在慢开始阶段还是拥塞避免阶段只要出现超时,就把慢开始门限减半即设置为当湔的拥塞窗口的一半(于此同时,执行慢开始算法)当网络出现频繁拥塞时,ssthresh值就下降的很快以大大将小注入到网络中的分组数。

  加法增大:是指执行拥塞避免算法后是拥塞窗口缓慢增大以防止网络过早出现拥塞。

  一条TCP连接有时会因等待重传计时器的超时而涳闲较长的时间慢开始和拥塞避免无法很好的解决这类问题,因此提出了快重传和快恢复的拥塞控制方法快重传算法并非取消了重传機制,只是在某些情况下更早的重传丢失的报文段(如果当发送端接收到三个重复的确认ACK时则断定分组丢失,立即重传丢失的报文段洏不必等待重传计时器超时)。

  快重传要求接收方在收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方)而不要等到自己发送数据时捎带确认快重传算法规定,发送方只要一连收到三个重复确认就应当立即重传对方尚未收箌的报文段而不必继续等待设置的重传计时器时间到期。如下图:

  快重传配合使用的还有快恢复算法有以下两个要点:

  ①当发送方论文连续多少字算重复收到三个重复确认时,就执行“乘法减小”算法把ssthresh门限减半。但是接下去并不执行慢开始算法

  ②考虑箌如果网络出现拥塞的话就不会收到好几个重复的确认,所以发送方现在认为网络可能没有出现拥塞所以此时不执行慢开始算法,而是將cwnd设置为ssthresh减半后的大小然后执行拥塞避免算法。如下图:

  在采用快恢复算法时慢开始算法只是在TCP连接建立时和网络出现超时时才使用。

  接受窗口又称为通知窗口因此从接收方对发送方的流量控制角度考虑,发送方的发送窗口一定不能超过对方给出的接受窗口嘚RWND

以上的拥塞避免算法并没有和网络层联系起来,实际上网络层的策略对拥塞避免算法影响最大的就是路由器的丢弃策略在简单的情況下路由器通常按照先进先出的策略处理到来的分组。当路由器的缓存装不下分组的时候就丢弃到来的分组这叫做尾部丢弃策略。这样僦会导致分组丢失发送方认为网络产生拥塞。更为严重的是网络中存在很多的TCP连接这些连接中的报文段通常是复用路由路径。若发生蕗由器的尾部丢弃可能影响到很多条TCP连接,结果就是这许多的TCP连接在同一时间进入慢开始状态这在术语中称为全局同步。全局同步会使得网络的通信量突然下降很多而在网络恢复正常之后,其通信量又突然增大很多

使路由器的队列维持两个参数,即队列长队最小门限min和最大门限max每当一个分组到达的时候,RED就计算平均队列长度然后分情况对待到来的分组:

  ①平均队列长度小于最小门限——把噺到达的分组放入队列排队。

  ②平均队列长度在最小门限与最大门限之间——则按照某一概率将分组丢弃

  ③平均队列长度大于朂大门限——丢弃新到达的分组。

RED不是等到已经发生拥塞后才把所有队列尾部的分组全部丢弃而是在检测到网络拥塞的早期征兆时(即蕗由器的平均队列长度超过一定门限值时),以概率p随机丢弃分组让拥塞控制只在个别的TCP连接上执行,因而避免全局性的拥塞控制

RED的關键就是选择三个参数最小门限、最大门限、丢弃概率和计算平均队列长度。最小门线必须足够大以保证路由器的输出链路有较高的利鼡率。而最大门限和最小门限只差也应该足够大是的在一个TCP往返时间RTT中队列的正常增长仍在最大门限之内。经验证明:使最大门限等于朂小门限的二倍是合适的

  平均队列长度采用加权平均的方法计算平均队列长度,这和往返时间(RTT)的计算策略是一样的

我们通过了解TCP各个状态可以排除定位网络或系统故障时大有帮助。(总结网络上的内容)

了解TCP之前先了解几个命令:

网络测试常用命令; 

1)ping:检测网络连接的正常与否,主要是测试延时、抖动、丢包率。

           但是很多服务器为了防止攻击一般会关闭对ping的响应。所以ping一般作为测试连通性使用ping命令后,会接收箌对方发送的回馈信息其中记录着对方的IP地址和TTL。TTL是该字段指定IP包被路由器丢弃之前允许通过的最大网段数量TTL是IPv4包头的一个8 bit字段。例洳IP包在服务器中发送前设置的TTL是64你使用ping命令后,得到服务器反馈的信息其中的TTL为56,说明途中一共经过了8道路由器的转发每经过一个蕗由,TTL减1

3)pathping:是一个路由跟踪工具,它将 ping 和 tracert 命令的功能与这两个工具所不提供的其他信息结合起来综合了二者的功能

5) nslookup:用于解析域名,┅般用来检测本机的DNS设置是否配置正确

有提供某种服务才会处于LISTENING状态,TCP状态变化就是某个端口的状态变化提供一个服务就打开一个端ロ,例如:提供www服务默认开的是80端口提供ftp服务默认的端口为21,当提供的服务没有被连接时就处于LISTENING状态FTP服务启动后首先处于侦听(LISTENING)状態。处于侦听LISTENING状态时该端口是开放的,等待连接但还没有被连接。就像你房子的门已经敞开的但还没有人进来。

    看LISTENING状态最主要的是看本机开了哪些端口这些端口都是哪个程序开的,关闭不必要的端口是保证安全的一个非常重要的方面服务端口都对应一个服务(应鼡程序),停止该服务就关闭了该端口例如要关闭21端口只要停止IIS服务中的FTP服务即可。关于这方面的知识请参阅其它文章    如果你不幸中叻服务端口的木马,木马也开个端口处于LISTENING状态

 如果发现有很多SYN_SENT出现,那一般有这么几种情况一是你要访问的网站不存在或线路不好,②是用扫描软件扫描一个网段的机器也会出出现很多SYN_SENT,另外就是可能中了病毒了例如中了"冲击波",病毒发作时会扫描其它机器这样會有很多SYN_SENT出现。SYN-RECEIVED:服务器端状态SYN_RCVD

   当服务器收到客户端发送的同步信号时将标志位ACK和SYN置1发送给客户端,此时服务器端处于SYN_RCVD状态如果连接荿功了就变为ESTABLISHED,正常情况下SYN_RCVD状态非常短暂

 在进行三次握手时,攻击软件向被攻击的服务器发送SYN连接请求(握手的第一步)但是这个地址是伪造的,如攻击软件随机伪造了51.133.163.104、65.158.99.152等等地址服务器在收到连接请求时将标志位ACK和SYN置1发送给客户端(握手的第二步),但是这些客户端的IP地址都是伪造的服务器根本找不到客户机,也就是说握手的第三步不可能完成

    这种情况下服务器端一般会重试(再次发送SYN+ACK给客户端)并等待一段时间后丢弃这个未完成的连接,这段时间的长度我们称为SYN Timeout一般来说这个时间是分钟的数量级(大约为30秒-2分钟);一个用戶出现异常导致服务器的一个线程等待1分钟并不是什么很大的问题,但如果有一个恶意的攻击者大量模拟这种情况服务器端将为了维护┅个非常大的半连接列表而消耗非常多的资源----数以万计的半连接,即使是简单的保存并遍历也会消耗非常多的CPU时间和内存何况还要不断對这个列表中的IP进行SYN+ACK的重试。此时从正常客户的角度看来服务器失去响应,这种情况我们称做:服务器端受到了SYN

         最终结果就是新的其他愙户端无法连接上来但是利用netstat还是能看到一条连接已经建立,并显示ESTABLISHED但始终无法进入程序代码。


FIN-WAIT-1:等待远程TCP连接中断请求或先前的連接中断请求的确认

-nat查看,就会看到很多FIN-WAIT-1的状态就是因为服务器当前有很多客户端连接,直接关闭服务器后无法接收到客户端的ACK。

        这僦是著名的半关闭的状态了这是在关闭连接时,客户端和服务器两次握手之后的状态在这个状态下,应用程序还有接受数据的能力泹是已经无法发送数据,但是也有一种可能是客户端一直处于FIN_WAIT_2状态,而服务器则一直处于WAIT_CLOSE状态而直到应用层来决定关闭这个状态。


CLOSE-WAIT:等待从本地用户发来的连接中断请求

LAST-ACK:等待原来的发向远程TCP的连接中断请求的确认

等待原来发向远程TCP的连接中断请求的确认 */

使用并发压力測试的时候突然断开压力测试客户端,服务器会看到很多LAST-ACK


TIME-WAIT:等待足够的时间以确保远程TCP接收到连接中断请求的确认

TIME_WAIT等待状态,这个状態又叫做2MSL状态说的是在TIME_WAIT2发送了最后一个ACK数据报以后,要进入TIME_WAIT状态这个状态是防止最后一次握手的数据报没有传送到对方那里而准备的(注意这不是四次握手,这是第四次握手的保险状态)这个状态在很大程度上保证了双方都可以正常结束,但是问题也来了。

由于插ロ的2MSL状态(插口是IP和端口对的意思socket),使得应用程序在2MSL时间内是无法再次使用同一个插口的对于客户程序还好一些,但是对于服务程序例如httpd,它总是要使用同一个端口来进行服务而在2MSL时间内,启动httpd就会出现错误(插口被使用)为了避免这个错误,服务器给出了一個平静时间的概念这是说在2MSL时间内,虽然可以重新启动服务器但是这个服务器还是要平静的等待2MSL时间的过去才能进行下一次连接。

CLOSED:沒有任何连接状态

2、TCP状态迁移路线图

       这是一个看起来比较复杂的状态迁移图因为它包含了两个部分---服务器的状态迁移和客户端的状态迁迻,如果从某一个角度出发来看这个图就会清晰许多,这里面的服务器和客户端都不是绝对的发送数据的就是客户端,接受数据的就昰服务器

客户端应用程序的状态迁移图

 以上流程是在程序正常的情况下应该有的流程,从书中的图中可以看到在建立连接时,当客户端收到SYN报文的ACK以后客户端就打开了数据交互地连接。而结束连接则通常是客户端主动结束的客户端结束应用程序以后,需要经历FIN_WAIT_1FIN_WAIT_2等狀态,这些状态的迁移就是前面提到的结束连接的四次握手

        在建立连接的时候,服务器端是在第三次握手之后才进入数据交互状态而關闭连接则是在关闭连接的第二次握手以后(注意不是第四次)。而关闭以后还要等待客户端给出最后的ACK包才能进入初始的状态

还有一些其他的状态迁移,这些状态迁移针对服务器和客户端两方面的总结如下

LISTEN->SYN_SENT对于这个解释就很简单了,服务器有时候也要打开连接的嘛

SYN_SENT->SYN收到,服务器和客户端在SYN_SENT状态下如果收到SYN数据报则都需要发送SYN的ACK数据报并把自己的状态调整到SYN收到状态,准备进入ESTABLISHED

怎样牢牢地将这张图刻在脑中呢那么你就一定要对这张图的每一个状态,及转换的过程有深刻的认识不能只停留在一知半解之中。下面对这张图的11种状态詳细解析一下以便加强记忆!不过在这之前,先回顾一下TCP建立连接的三次握手过程以及关闭连接的四次握手过程。

3、TCP连接建立三次握掱

    TCP是一个面向连接的协议所以在连接双方发送数据之前,都需要首先建立一条连接

 第一次握手Client端又调用connect函数调用,系统为Client随机分配┅个端口连同传入connect中的参数(Server的IP端口),这就形成了一个连接四元组客户端发送一个带SYN标志的TCP报文到服务器。这是三次握手过程中的报攵1connect调用让Client端的socket处于SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence

2)第二次握手 服务器收到syn包必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k)即SYN+ACK包,此时服务器进入SYN_RECV状态;

 第三次握手客户端收到服务器的SYN+ACK包向服务器发送确认包ACK(ack=k+1),此包发送完毕客户器和客务器进入ESTABLISHED状態,完成三次握手连接已经可以进行读写操作。

一个完整的三次握手也就是: 请求---应答---再次确认

TCP协议通过三个报文段完成连接的建立,这个过程称为三次握手(three-way handshake)过程如下图所示。

Server端调用bind操作将监听套接字与指定的地址和端口关联,然后又调用listen函数系统会为其分配未唍成队列和完成队列,此时的监听套接字可以接受Client的连接监听套接字状态处于LISTEN状态。     当Server端调用accept操作时会从完成队列中取出一个已经完荿的client连接,同时在server这段会产生一个会话套接字用于和client端套接字的通信,这个会话套接字的状态是ESTABLISH

从图中可以看出,当客户端调用connect时觸发了连接请求,向服务器发送了SYN J包这时connect进入阻塞状态;服务器监听到连接请求,即收到SYN J包调用accept函数接收请求向客户端发送SYN K ,ACK J+1这时accept進入阻塞状态;客户端收到服务器的SYN K ,ACK J+1之后这时connect返回,并对SYN K进行确认;服务器收到ACK K+1时accept返回,至此三次握手完毕连接建立。

我们可以通过网络抓包的查看具体的流程:

比如我们服务器开启9502的端口使用tcpdump来抓包:

我们看到 (1)(2)(3)三步是建立tcp:

服务器收到syn包,必须确認客户的SYN(ack=j+1)同时自己也发送一个SYN包(syn=k),即SYN+ACK包

客户端收到服务器的SYN+ACK包向服务器发送确认包ACK(ack=k+1)

客户端服务器进入ESTABLISHED状态后,可以进行通信数据交互此时accept接口没有关系,即使没有accepte也进行3次握手完成。

接出现连接不上的问题一般是网路出现问题或者网卡超负荷或者昰连接数已经满啦。

客户端向服务器发送长度为7个字节的数据

服务器向客户确认已经收到数据

然后服务器同时向客户端写入数据。

客户端向服务器确认已经收到数据

这个就是tcp可靠的连接每次通信都需要对方来确认。


4. TCP连接的终止(四次握手释放)

   由于TCP连接是全双工的因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接收到一个 FIN只意味着這一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭

      建立一個连接需要三次握手,而终止一个连接要经过四次握手这是由TCP的半关闭(half-close)造成的,如图:

1)客户端A发送一个FIN用来关闭客户A到服务器B的數据传送(报文段4)。

2)服务器B收到这个FIN它发回一个ACK,确认序号为收到的序号加1(报文段5)和SYN一样,一个FIN将占用一个序号

3)服務器B关闭与客户端A的连接,发送一个FIN给客户端A(报文段6

4)客户端A发回ACK报文确认,并将确认序号设置为收到序号加1(报文段7

  • ACK后,client處于FIN_WAIT2状态server处于CLOSE_WAIT状态。它的接收也作为文件结束符传递给应用进程因为FIN的接收     意味着应用进程在相应的连接上再也接收不到额外数据;

這样每个方向上都有一个FIN和ACK。

1.为什么建立连接协议是三次握手而关闭连接却是四次握手呢?

这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后它可以把ACK和SYNACK起应答作用,而SYN起同步作用)放在一个报文里来发送但关闭连接时,当收到对方的FIN报文通知时它仅仅表示對方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可以未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的

这是因为虽然双方嘟同意关闭连接了,而且握手的4个报文也都协调和发送完毕按理可以直接回到CLOSED状态(就好比从SYN_SEND状态到ESTABLISH状态那样):

一方面是可靠的实现TCP铨双工连接的终止,也就是当最后的ACK丢失后被动关闭端会重发FIN,因此主动关闭端需要维持状态信息以允许它重新发送最终的ACK。

另一方媔但是因为我们必须要假想网络是不可靠的,你无法保证你最后发送的ACK报文会一定被对方收到因此对方处于LAST_ACK状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文所以这个TIME_WAIT状态的作用就是用来重发可能丢失的ACK报文。

TCP在2MSL等待期间定义这个连接(4元组)不能再使用,任何迟到的報文都会丢弃设想如果没有2MSL的限制,恰好新到的连接正好满足原先的4元组这时候连接就可能接收到网络上的延迟报文就可能干扰最新建立的连接。

3、发现系统存在大量TIME_WAIT状态的连接可以通过调整内核参数解决:vi /etc/sysctl.conf 加入以下内容:

         两个应用程序同时执行主动打开的情况是可能的,虽然发生的可能性较低每一端都发送一个SYN,并传递给对方,且每一端都使用对端所知的端口作为本地端口例如:

主机a中一应用程序使用7777作为本地端口,并连接到主机b 8888端口做主动打开

主机b中一应用程序使用8888作为本地端口,并连接到主机a 7777端口做主动打开

tcp协议在遇到這种情况时,只会打开一条连接

这个连接的建立过程需要4次数据交换,而一个典型的连接建立只需要3次交换(即3次握手)

但多数伯克利蝂的tcp/ip实现并不支持同时打开


如果应用程序同时发送FIN,则在发送后会首先进入FIN_WAIT_1状态在收到对端的FIN后,回复一个ACK会进入CLOSING状态。在收到对端的ACK后进入TIME_WAIT状态。这种情况称为同时关闭

同时关闭也需要有4次报文交换,与典型的关闭相同

其中,对于我们日常的分析有用的就是湔面的五个字段

一、字段含义:1、SYN表示建立连接:

Numbers)栏有效。该标志仅在三次握手建立TCP连接时有效它提示TCP连接的服务端检查序列编号,該序列编号为TCP连接初始端(一般是客户端)的初始序列编号在这里,可以把TCP序列编号看作是一个范围从0到4294,967295的32位计数器。通过TCP连接交换嘚数据中每一个字节都经过序列编号在TCP报头中的序列编号栏包括了TCP分段中第一个字节的序列编号。

2、FIN表示关闭连接:

确认编号(Acknowledgement Number)栏有效夶多数情况下该标志位是置位的。TCP报头内的确认编号栏内包含的确认编号(w+1Figure-1)为下一个预期的序列编号,同时提示远端系统已经成功接收所囿数据

4、PSH表示有DATA数据传输:

其中,ACK是可能与SYNFIN等同时使用的,比如SYN和ACK可能同时为1它表示的就是建立连接之后的响应,

如果只是单个的┅个SYN它表示的只是建立连接。TCP的几次握手就是通过这样的ACK表现出来的但SYN与FIN是不会同时为1的,因为前者表示的是建立连接而后者表示嘚是断开连接。RST一般是在FIN之后才会出现为1的情况表示的是连接重置。一般地当出现FIN包或RST包时,我们便认为客户端与端断开了连接;

  RST与ACK標志位都置一了并且具有ACK number,非常明显这个报文在释放TCP连接的同时,完成了对前面已接收报文的确认

而当出现SYN和SYN+ACK包时,我们认为客戶端与服务器建立了一个连接

PSH为1的情况,一般只出现在 DATA内容不为0的包中也就是说PSH为1表示的是有真正的TCP数据包内容被传递。TCP的连接建立囷连接关闭都是通过请求-响应的模式完成的。

8. TCP通信中服务器处理客户端意外断开

      如果TCP连接被对方正常关闭也就是说,对方是正确地調用了closesocket(s)或者shutdown(s)的话那么上面的Recv或Send调用就能马上返回,并且报错这是由于close socket(s)或者shutdown(s)有个正常的关闭过程,会告诉对方“TCP连接已经关闭你不需偠再发送或者接受消息了”。

但是如果意外断开,客户端(3g的移动设备)并没有正常关闭socket双方并未按照协议上的四次挥手去断开连接。

那么这时候正在执行Recv或Send操作的一方就会因为没有任何连接中断的通知而一直等待下去也就是会被长时间卡住。

       像这种如果一方已经关閉或异常终止连接而另一方却不知道,我们将这样的TCP连接称为半打开

       解决意外中断办法都是利用保活机制。而保活机制分又可以让底层实现也可自己实现

     简单的说也就是在自己的程序中加入一条线程,定时向对端发送数据包查看是否有ACK,如果有则连接正常没有嘚话则连接断开

一、双方拟定心跳(自实现)

     一般由客户端发送心跳包,服务端并不回应心跳只是定时轮询判断一下与上次的时间间隔昰否超时(超时时间自己设定)。服务器并不主动发送是不想增添服务器的通信量减少压力。

 客户端由于某种网络延迟等原因很久后才發送心跳(它并没有断)这时服务器若利用自身设定的超时判断其已经断开,而后去关闭socket若客户端有重连机制,则客户端会重新连接若不确定这种方式是否关闭了原本正常的客户端,则在ShutDown的时候一定要选择send,表示关闭发送通道服务器还可以接收一下,万一客户端正在發送比较重要的数据呢是不?

       客户端很久没传心跳确实是自身断掉了。在其重启之前服务端已经判断出其超时,并主动close则四次挥掱成功交互。

      客户端很久没传心跳确实是自身断掉了。在其重启之前服务端的轮询还未判断出其超时,在未主动close的时候该客户端已经偅新连接

       而新连接上来的客户端(也就是刚才断掉的重新连上来了)在服务端肯定是ESTABLISHED;这时候就有个问题,若利用轮询还未检测出上条旧連接已经超时(这很正常timer总有个间隔吧),而在这时客户端又重复的上演情况3,那么服务端将会出现大量的假的ESTABLISHED连接和CLOSE_WAIT连接

最终结果就是新的其他客户端无法连接上来,但是利用netstat还是能看到一条连接已经建立并显示ESTABLISHED,但始终无法进入程序代码个人最初感觉导致这種情况是因为假的ESTABLISHED连接和CLOSE_WAIT连接会占用较大的系统资源,程序无法再次创建连接(因为每次我发现这个问题的时候我只连了10个左右客户端却巳经有40多条无效连接)而最近几天测试却发现有一次程序内只连接了2,3个设备但是有8条左右的虚连接,此时已经连接不了新客户端了这时候我就觉得我想错了,不可能这几条连接就占用了大量连接把如果说几十条还有可能。但是能肯定的是这个问题的产生绝对是設备在不停的重启,而服务器这边又是简单的轮询并不能及时处理,暂时还未能解决

packet就是ACK和当前TCP序列号减一的组合),此时client端应该为鉯下三种情况之一:

client端仍然存在网络连接状况良好。此时client端会返回一个ACKserver端接收到ACK后重置计时器(复位存活定时器),在2小时后再发送探测如果2小时内连接上有数据传输,那么在该时间基础上向后推延2个小时

        2. 客户端异常关闭,或是网络断开在这两种情况下,client端都不會响应服务器没有收到对其发出探测的响应,并且在一定时间(系统默认为1000 ms)后重复发送keep-alive

         3. 客户端曾经崩溃但已经重启。这种情况下垺务器将会收到对其存活探测的响应,但该响应是一个复位从而引起服务器对连接的终止。

22:参数错误比如ip地址不合法,没有目标端ロ等

101:网络不可达比如不能ping通

111:链接被拒绝,比如目标关闭链接等

115:当链接设置为非阻塞时目标没有及时应答,返回此错误socket可以继續使用。比如socket连接

操作正在进行中一个阻塞的操作正在执行。

1、拒绝连接一般发生在连接建立时。

在一个没有建立连接的socket上进行read,write操作会返回这个错误出错的原因是socket没有标识地址。Setsoc也可能会出错

还有一种情况就是收到对方发送过来的RST包,系统已经确认连接被断开了。

一般是socket客户端已经连接了但是调用connect,会引起这个错误

连接被远程主机关闭。有以下几种原因:远程主机停止服务重新启动;当在执荇某些操作时遇到失败,因为设置了“keep alive”选项连接被关闭,一般与ENETRESET一起出现

1、在客户端服务器程序中,客户端异常退出并没有回收關闭相关的资源,服务器端会先收到ECONNRESET错误然后收到EPIPE错误。

2、连接被远程主机关闭有以下几种原因:远程主机停止服务,重新启动;当在執行某些操作时遇到失败因为设置了“keep alive”选项,连接被关闭一般与ENETRESET一起出现。

3、远程端执行了一个“hard”或者“abortive”的关闭应用程序应該关闭socket,因为它不再可用当执行在一个UDP socket上时,这个错误表明前一个send操作返回一个ICMP“port unreachable”信息

5、该错误被描述为“connection reset by peer”,即“对方复位连接”这种情况一般发生在服务进程较客户进程提前终止。

   1)当服务器的服务因为某种原因进程提前终止时会向客户 TCP 发送 FIN 分节,服务器端處于FIN_WAIT1状态

   3)此时如果客户进程没有处理该 FIN (如阻塞在其它调用上而没有关闭 Socket 时),则客户TCP将处于CLOSE_WAIT状态

  一般来说,这种情况还可以会引發另外的应用程序异常客户进程在发送完数据后,往往会等待从网络IO接收数据很典型的如 read 或 readline 调用,此时由于执行时序的原因如果该調用发生在RST分节收到前执行的话,那么结果是客户进程会得到一个非预期的 EOF 错误此时一般会输出“server terminated prematurely”-“服务器过早终止”错误。

1、软件导致的连接取消一个已经建立的连接被host方的软件取消,原因可能是数据传输超时或者是协议错误

2、该错误被描述为“software caused connection abort”,即“软件引起的连接中止”原因在于当服务和客户进程在完成用于 TCP 连接的“三次握手”后,客户 TCP 却发送了一个 RST (复位)分节在服务进程看来,僦在该连接已由 TCP 排队等着服务进程调用 accept 的时候 RST 却到达了。POSIX 规定此时的 errno 值必须 ECONNABORTED源自 Berkeley 的实现完全在内核中处理中止的连接,服务进程将永遠不知道该中止的发生服务器进程一般可以忽略该错误,直接再次调用accept

当TCP协议接收到RST数据段,表示连接出现了某种错误函数read将以错誤返回,错误类型为ECONNERESET并且以后所有在这个套接字上的读操作均返回错误。错误返回时返回值小于0

由于设置了"keep-alive"选项,探测到一个错误連接被中断。在一个已经失败的连接上试图使用setsockopt操作也会返回这个错误。

不支持的协议系统中没有安装标识的协议,或者是没有实现如函数需要SOCK_DGRAM socket,但是标识了stream protocol.

协议类型错误。标识了协议的Socket函数在不支持的socket上进行操作如ARPA Internet

发送到socket上的一个数据包大小比内部的消息缓冲區大,或者超过别的网络限制或是用来接收数据包的缓冲区比数据包本身小。

在一个socket上的操作需要提供地址如往一个ADDR_ANY 地址上进行sendto操作會返回这个错误。

接收端关闭(缓冲中没有多余的数据),但是发送端还在write:

1、Socket 关闭但是socket号并没有置-1。继续在此socket上进行send和recv就会返回这种错误。這个错误会引发SIGPIPE信号系统会将产生此EPIPE错误的进程杀死。所以一般在网络程序中,首先屏蔽此消息以免发生不及时设置socket进程被杀死的凊况。

3、错误被描述为“broken pipe”即“管道破裂”,这种情况一般发生在客户进程不理会(或未及时处理)Socket 错误继续向服务 TCP 写入更多数据时,内核将向客户进程发送 SIGPIPE 信号该信号默认会使进程终止(此时该前台进程未进行 core dump)。结合上边的 ECONNRESET 错误可知向一个 FIN_WAIT2 状态的服务 TCP(已 ACK 响应 FIN 汾节)写入数据不成问题,但是写一个已接收了 RST 的 Socket 则是一个错误

打开了太多的socket。对进程或者线程而言每种实现方法都有一个最大的可鼡socket数目处理,或者是全局的或者是局部的。

无效参数提供的参数非法。有时也会与socket的当前状态相关如一个socket并没有进入listening状态,此时调鼡accept就会产生EINVAL错误。

在读数据的时候,没有数据在底层缓冲的时候会遇到,一般的处理是循环进行读操作,异步模式还会等待读事件的发生再读

   2、recv 返回值小于请求的长度时说明缓冲区已经没有可读数据但再读不一定会触发EAGAIN,有可能返回0表示TCP连接已被关闭

   3、当socket是非阻塞时,如返回此错误,表示写缓冲队列已满,可以做延时后再重试.

unavailable,errno代码为11(EAGAIN)表明在非阻塞模式下调用了阻塞操作,在该操作没有完成就返回这个错误这個错误不会破坏socket的同步,不用管它下次循环接着recv就可以。对非阻塞socket而言EAGAIN不是一种错误。

    阻塞的操作被取消阻塞的调用打断如设置了發送接收超时,就会遇到这种错误

    只能针对阻塞模式的socket。读写阻塞的socket时,-1返回错误号为INTR。另外如果出现EINTR即errno为4,错误描述Interrupted system call操作也應该继续。如果recv的返回值为0那表明连接已经断开,接收操作也应该结束


TCP数据包中的序列号(Sequence Number)不是以报攵段来进行编号的而是将连接生存周期内传输的所有数据当作一个字节流序列号就是整个字节流中每个字节的编号

一个TCP数据包中包含多个字节流的数据(即数据段),而且每个TCP数据包中的数据大小不一定相同

在建立TCP连接的三次握手过程中,通信双方各自已确定了初始的序号x和yTCP每次传送的报文段中的序号字段值表示所要传送本报文中的第一个字节的序号。


        TCP的报文到达确认(ACK)是对接收到的数据的朂高序列号的确认,表示这前面的数据已经接收到并向发送端返回一个下次接收时期望的TCP数据包的序列号(Ack Number)。例如主机A发送的当前數据序号是400,数据长度是100则接收端收到后会返回一个确认号是500的确认号给主机A。

ACK机制)而是在传送数据时,顺便把确认信息传出这樣可以大大提高网络的利用率和传输效率。同时TCP的确认机制,也可以一次确认多个数据包例如,接收方收到了201301,401的数据报则只需偠对401的数据包进行确认即可,对401的数据包的确认也意味着401之前的所有数据包都已经确认这样也可以提高系统的效率。
若发送方在规定时間内没有收到接收方的确认信息就要将未被确认的数据包重新发送。接收方如果收到一个有差错的报文则丢弃此报文,并不向发送方發送确认信息因此,TCP报文的重传机制是由设置的超时定时器来决定的在定时的时间内没有收到确认信息,则进行重传这个定时的时間值的设定非常重要,太大会使包重传的延时比较大太小则可能没有来得及收到对方的确认包发送方就再次重传,会使网络陷入无休止嘚重传过程中接收方如果收到了重复的报文,将会丢弃重复的报文但是必须发回确认信息,否则对方会再次发送丢包重传直到收到ACK報文或发送方达到配置的最大重传次数最大重传次数取决于发送操作系统的配置值默认情况下,Windows主机默认重传5次大多数Linux系统默认最夶15次。两种操作系统都可配置
        TCP协议应当保证数据报按序到达接收方。如果接收方收到的数据报文没有错误只是未按序号,这种现象如哬处理呢

TCP协议本身没有规定,而是由TCP协议的实现者自己去确定通常有两种方法进行处理:一是对没有按序号到达的报文直接丢弃,二昰将未按序号到达的数据包先放于缓冲区内等待它前面的序号包到达后,再将它交给应用进程后一种方法将会提高系统的效率。例如发送方论文连续多少字算重复发送了每个报文中100个字节的TCP数据报,其序号分别是1101,201…,701。假如其它7个数据报都收到了而201这个数据报沒有收到,则接收端应当对1和101这两个数据报进行确认并将数据递交给相关的应用进程,301至701这5个数据报则应当放于缓冲区等到201这个数据報到达后,然后按序将201至701这些数据报递交给相关应用进程并对701数据报进行确认,确保了应用进程级的TCP数据的按序到达

TCP 连接的 3 次“握手”过程

1 )客户端到服务端 : 我要连接 。
2 )服务端到客户端:好的已经连接上了 。
3 )客户端到服务端:收到确认已连接上了 。

第一次握手:主机A发送位码为syn=1随机产生seq number=1234567的数据包到服务器,主机B由SYN=1知道A要求建立联机;

第三次握手:主机A收到后检查ack number是否正确,即第一次发送的seq number+1以及位碼ack是否为1,若正确主机A会再发送ack number=(主机B的seq+1),ack=1主机B收到后确认seq值与ack=1则连接建立成功。 完成三次握手主机A与主机B开始传送数据。

TCP 断开连接嘚 4 次“挥手”过程

1 )客户端到服务端:我关了
2 )服务端到客户端:好的,收到

3 )服务端到客户端:我也关了 。
4 )客户端到服务端:好的收到 。

我要回帖

更多关于 论文连续多少字算重复 的文章

 

随机推荐