tcp两端同时发送连接请求(一个tcp连接可以发送多少个http请求)

      最后更新:2023-03-26 15:23:41 手机定位技术交流文章

      TCP/IP -- 2

      TCP/IP中有两个具有代表性的传输层协议,它们分别是TCP和UDP。TCP提供可靠的通信传输,而UDP则常被用于让广播和细节调控交给应用的通信传输。 IP首部中有一个协议字段,用来标识网络层的上一层所采用的是哪一种传输层协议。根据这个字段的协议号,就可以识别IP传输的数据部分究竟是TCP的内容,还是UDP的内容。同样,传输层的TCP和UDP,为了识别自己所传输的数据部分究竟应该发给哪个应用,也设定了这样一个编号。TCP/IP的众多应用协议大多以客户端/服务端的形式运行。客户端类似于客户的意思,是请求的发起端。而服务端则表示提供服务的意思,是请求的处理端。另外,作为服务端的程序有必要提前启动,准备接收客户端的请求。否则即使有客户端的请求发过来,也无法做到响应的处理。这些服务端程序在UNIX系统中叫做守护进程。例如HTTP的服务端程序是httpd(HTTP守护进程),而ssh的服务端程序是sshd(SSH守护进程)。在UNIX中并不需要将这些守护进程逐个启动,而是启动一个可以代表它们接收客户端请求的inetd(互联网守护进程)服务程序即可。它是一种超级守护进程,该超级守护进程收到客户端请求以后会创建新的进程并转换为sshd等各个守护进程。确认一个请求究竟发给的是哪个服务端(守护进程),可以通过所收到数据包的目标端口号轻松识别。TCP:TCP是面向连接的、可靠的流协议。流就是指不间断的数据结构,你可以把它想象成排水管道中的水流。当应用程序采用TCP发送消息时,虽然可以保证发送的顺序,但还是犹如没有任何间隔的数据流发送给接收端。TCP为提供可靠性传输,实行"顺序控制"或"重发控制"机制。此外还具备"流控制(流量控制)"、"拥塞控制"、提高网络利用率等众多功能。UDP:UDP是不具有可靠性的数据报协议。细微的处理它会交给上层的应用去完成。在UDP的情况下,虽然可以确保发送消息的大小,却不能保证消息一定会到达。因此,应用有时会根据自己的需求进行重发处理。TCP与UDP的区分:TCP用于在传输层有必要实现可靠传输的情况。由于它是面向有连接并具备顺序控制、重发控制等机制的,所以它可以为应用提供可靠传输。UDP主要用于那些对于高速传输和实时性有较高要求的通信或广播通信。数据链路和IP中的地址,分别指的是MAC地址和IP地址。前者用来识别同一链路中不同的计算机,后者用来识别TCP/IP网络中互连的主机和路由器。在传输层中也有这种类似于地址的概念,那就是端口号。端口号用来识别同一台计算机中进行通信的不同应用程序。因此,它也被称为程序地址。TCP/IP或UDP/IP通信中通常采用5个信息来识别一个通信。它们是"源IP地址"、"目标IP地址"、"协议号"、"源端口号"、"目标端口号"。只要其中某一项不同,则被认为是其他通信。标准既定的端口号:这种方法也叫静态方法。它是指每个应用程序都有其指定的端口号。但并不是说可以随意使用任何一个端口号。每个端口号都有其对应的使用目的。时序分配法:服务器有必要确定监听端口号,但是接收服务的客户端没必要确定端口号。在这种方法下,客户端应用程序可以完全不用自己设置端口号,而全权交给操作系统进行分配。操作系统可以为每个应用程序分配互不冲突的端口号。根据这种动态分配端口号的机制,即使是同一客户端程序发起多个TCP连接,识别这些通信连接的5部分数字也不会全部相同。端口号由其使用的传输层协议决定。因此,不同的传输协议可以使用相同的端口号。数据到达IP层后,会先检查IP首部中的协议号,再传给相应协议的模块。如果是TCP则传给TCP模块,如果是UDP则传给UDP模块去做端口号的处理。即使是同一端口号,由于传输协议是各自独立地进行处理,因此相互之间不会受到影响。UDP不提供复杂的控制机制,利用IP提供面向无连接的通信服务。并且它是将应用程序发来的数据在收到的那一刻,立刻按照原样发送到网络上的一种机制。即使是出现网络拥堵的情况,UDP也无法进行流量控制等避免网络拥塞的行为。此外,传输途中即使出现丢包,UDP也不负责重发。甚至当出现包的到达顺序乱掉时也没有纠正功能。如果需要这些细节控制,那么不得不交由采用UDP的应用程序去处理。由于UDP面向无连接,它可以随时发送数据。再加上UDP本身的处理既简单又高效,因此经常用于以下几个方面:TCP是对"传输、发送、通信"进行"控制"的"协议"。它充分地实现了数据传输时各种控制功能,可以进行丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。TCP作为一种面向有连接的协议,只有在确认通信对端存在时才会发送数据,从而可以控制通信流量的浪费。为了通过IP数据报实现可靠性传输,需要考虑很多事情。例如数据的破坏、丢包、重复以及分片顺序混乱等问题。TCP通过检验和、序列号、确认应答、重发控制、连接管理以及窗口控制等机制实现可靠性传输。在TCP中,当发送端的数据到达接收主机时,接收端主机会返回一个已收到消息的通知。这个消息叫做确认应答。序列号是按照顺序给发送数据的每一个字节都标上号码的编号。接收端查询接收数据TCP首部中的序列号和数据的长度,将自己下一步应该接受的序号作为应答返送回去。就这样,通过序列号和确认应答号,TCP可以实现可靠传输。重发超时是指在重发数据之前,等待确认应答到来的那个特定时间间隔。如果超过了这个时间仍未收到确认应答,发送端将进行数据重发。重发超时的计算既要考虑往返时间又要考虑偏差是有其原因的。根据网络环境的不同往返时间可能会产生大幅度的摇摆,之所以发生这种情况是因为数据包的分段是经过不同路线到达的。TCP/IP的目的是即使在这种环境下也要进行控制,尽量不要浪费网络流量。数据被重发之后若还是收不到确认应答,则进行再次发送。此时,等待确认应答的时间将会以2倍、4倍的指数函数延长。此外,数据也不会被无限、反复地重发。达到一定重发次数之后,如果仍没有任何确认应答返回,就会判断为网络或对端主机发生了异常,强制关闭连接。并且通知应用通信异常强行终止。TCP提供面向有连接的通信传输。面向有连接是指在数据通信开始之前先做好通信两端之间的准备工作。在数据通信之前,通过TCP首部发送一个SYN包作为建立连接的请求等待确认应答。如果对端发来确认应答,则认为可以进行数据通信。如果对端的确认应答未能到达,就不会进行数据通信。此外,在通信结束时会进行断开连接的处理。可以使用TCP首部用于控制的字段来管理TCP连接。一个连接的建立与断开,正常过程至少需要来回发送7个包才能完成。在建立TCP连接的同时,也可以确定发送数据包的单位,我们也可以称其为"最大消息长度"(MSS)。最理想的情况是,最大消息长度正好是IP中不会被分片处理的最大数据长度。MSS是在三次握手的时候,在两端主机之间被计算得出。两端的主机在发出建立连接请求时,会在TCP首部中写入MSS选项,告诉对方自己的接口能够适应的MSS的大小。然后会在两者之间选择一个较小的投入使用。TCP以1个段为单位,每发一个段进行一次确认应答的处理。这样的传输方式有一个缺点。那就是,包的往返时间越长通信性能就越低。为了解决这个问题,TCP引入了窗口这个概念。即使在往返时间较长的情况下,它也能控制网络性能的下降。窗口大小就是指无需等待确认应答而可以继续发送数据的最大值。在未使用窗口控制时,没有收到确认应答的数据都会被重发。而使用了窗口控制,某些确认应答即使丢失也无需重发。其次,我们来考虑一下某个报文段丢失的情况。接收主机如果收到一个自己应该接收的序号以外的数据时,会针对当前位置收到的数据返回确认应答。当某一报文段丢失后,发送端会一直收到序号为1001的确认应答,这个确认应答提醒发送端,"我想接收的是从1001开始的数据"。TCP提供一种机制可以让发送端根据接收端的实际接收能力控制发送的数据量。这就是所谓的流控制。它的具体操作是,接收端主机向发送端主机通知自己可以接收数据的大小,于是发送端会发送不超过这个限度的数据。这大小限度被称作窗口大小。窗口大小的值就是由接收端主机决定的。当接收端从3001号开始的数据段后其缓冲区即满,不得不暂时停止接收数据。之后,在收到发送窗口更新通知后通信才得以继续进行。有了窗口控制,收发主机之间可以不再以一个数据段为单位发送确认应答,也能够连续发送大量数据包。但是如果在通信刚开始时就发送大量数据,也有可能会引发其他问题。TCP为了防止该问题的出现,在通信一开始时就会通过一个叫做慢启动的算法得出的数值,对发送数据量进行控制。首先,为了在发送端调节所要发送数据的量,定义了一个叫做"拥堵窗口"的概念。于是在慢启动的时候,将这个拥堵窗口的大小设置为1个数据段(1 MSS)发送数据,之后每收到一次确认应答(ACK),拥堵窗口的值就加1。在发送数据包时,将拥堵窗口的大小与接收端主机通知的窗口大小做比较,然后按照它们当中较小那个值,发送比其还要小的数据量。如果重发采用超时机制,那么拥塞窗口的初始值可以设置为1以后再进行慢启动修正。有了上述这些机制,就可以有限的减少通信开始时连续发包导致的网络拥堵,还可以避免网络拥塞情况的发生。不过,随着包的每次往返,拥塞窗口也会以1、2、4等指数函数的增长,拥堵状况激增甚至导致网络拥塞的发生。为了防止这些,引入了慢启动阀值的概念。只要拥塞窗口的值超出这个阀值,在每收到一次确认应答时,只允许以下面这种比例放大拥塞窗口:TCP的通信开始时,并没有设置相应的慢启动阈值。而是在超时重传时,才会设置为当前拥塞窗口一半的大小。由于重复确认应答而触发的高速重发与超时重发机制的处理多少有些不同。因为前者要求至少3次的确认应答数据段到达对方主机后才触发,相比后者网络的拥堵要轻一些。而由重复确认应答进行高速重发控制时,慢启动阈值的大小被设置为当时窗口大小的一半,然后将窗口的大小设置为该慢启动阈值+3个数据段的大小。当TCP通信开始以后,网络吞吐量会逐渐上升,但是随着网络拥堵的发生吞吐量也会急剧下降。于是会再次进入吞吐量慢慢上升的过程。因此所谓TCP的吞吐量的特点就好像是在逐步占领网络带宽的感觉。UDP-Lite(Lightweight User Datagram Protocol,轻量级用户数据报协议)是扩展UDP机能的一种传输层协议。在基于UDP的通信当中如果校验和出现错误,所收到的包将被全部丢弃。然而,现实操作中,有些应用在面对这种情况时并不希望把已经收到的所有包丢弃。如果将UDP中校验和设置为无效,那么即使数据的一部分发生错误也不会将整个包废弃。不过,这不是一个很好的方法。因为如果发生的错误有可能是UDP首部中的端口号被破坏或是IP首部中的IP地址被破坏,就会产生严重后果。因此,不建议将校验和关闭。为了解决这些问题,UDP的修正版UDP-Lite协议就出现了。UDP-Lite提供与UDP几乎相同的功能,不过计算校验和的范围可以由应用自行决定。这个范围可以是包加上伪首部的校验和计算,可以是首部与伪首部的校验和计算,也可以是首部、伪首部与数据从起始到中间某个位置的校验和计算。有了这样的机制,就可以只针对不允许发生错误的部分进行校验和的检查。 对于其他部分,即使发生了错误,也会被忽略不计。而这个包也不会被丢弃,而是直接传给应用继续处理。SCTP(Stream Control Transmission Protocol,流控制传输协议)与TCP一样,都是对一种提供数据到达与否相关可靠性检查的传输层协议。其主要特点如下:SCTP主要用于进行通信的应用之间发送众多较小消息的情况。这些较小的应用消息被称作数据块(Chunk),多个数据块组成一个数据包。此外,SCTP具有支持多重宿主以及设定多个IP地址的特点。多重宿主是指同一台主机具备多种网络的接口。例如,笔记本电脑既可以连接以太网又可以连接无线LAN。同时使用以太网和无线LAN时,各自的NIC会获取到不同的IP地址。进行TCP通信,如果开始时使用的是以太网,而后又切换为无线LAN,那么连接将会被断开。因为从SYN到FIN包必须使用同一个IP地址。然而在SCTP的情况下,由于可以管理多个IP地址使其同时进行通信,因此即使出现通信过程当中以太网与无线LAN之间的切换,也能够保持通信不中断。所以SCTP可以为具备多个NIC的主机提供更可靠的传输。DCCP(Datagram Congestion Control Protocol,数据报拥塞控制协议)是一个辅助UDP的崭新的传输层协议。UDP没有拥塞控制机制。为此,当应用使用UDP发送大量数据包时极容易出现问题。互联网中的通信,即使使用UDP也应该控制拥塞。而这个机制开发人员很难将其融合至协议中,于是便出现了DCCP这样的规范。DCCP具有如下几个特点: TCP首部比UDP首部要复杂得多。TCP中没有表示包长度和数据长度的字段。可由IP层获知TCP的包长,由TCP的包长可知数据的长度。
      TCP/IP -- 2

      TCP采用哪些机制来实现可靠数据传输、流控和拥塞控制?

      1.采用面向连接的三次握手实现可靠对象传输。 2.使用数据窗口机制协商队列大小实现数据队列传输。3.通过序列化应答和必要时重发数据包,TCP 为应用程序提供了可靠的传输流和虚拟连接服务。下面是找到的长篇大论中比较好的文章:一、TCP协议1、TCP 通过以下方式提供可靠性:◆ 应用程序分割为TCP认为最合适发送的数据块。由TCP传递给IP的信息单位叫做报文段。◆ 当TCP发出一个报文段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能记时收到一个确认,它 就重发这个报文段。◆ 当TCP收到发自TCP连接另一端的数据,它将发送一个确认。这个确认不是立即发送,通常延迟几分之一秒。◆ TCP将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化如果收到报文段的检验和有差错,TCP将丢弃这个报文段和不确认收到这个报文段。◆ 既然TCP报文段作为IP数据报来传输,而IP数据报的到达可能失序,因此TCP报文段的到达也可能失序。如果必要,TCP将对收到的数据进行排序,将收到的数据以正确的顺序交给应用层。◆ 既然IP数据报会发生重复,TCP连接端必须丢弃重复的数据。◆ TCP还能提供流量控制,TCP连接的每一方都有固定大小的缓冲空间。TCP的接收端只允许另一端发送接收端缓冲区所能接纳的数据。这将防止较快主机致使较慢主机的缓冲区溢出。另外,TCP对字节流的内容不作任何解释。2、TCP首部:TCP数据被封装在一个IP数据报中,格式如下:IP首部20 TCP首部20 TCP首部TCP首部格式如下:16位源端口号 16位目的端口号32位序号32位确认序号4位首部长度 保留6位 URG ACK PSH RST SYN FIN 16位窗口大小16位检验和 16位紧急指针选项数据说明:(1)每个TCP段都包括源端和目的端的端口号,用于寻找发送端和接收端的应用进程。这两个值加上IP首部的源端IP地址和目的端IP地址唯一确定一个TCP连接。(2)序号用来标识从TCP发送端向接收端发送的数据字节流,它表示在这个报文段中的第一个数据字节。如果将字节流看作在两个应用程序间的单向流动,则TCP用序号对每个字节进行计数。(3)当建立一个新连接时,SYN标志变1。序号字段包含由这个主机选择的该连接的初始序号ISN,该主机要发送数据的第一个字节的序号为这个ISN加1,因为SYN标志使用了一个序号。(4)既然每个被传输的字节都被计数,确认序号包含发送确认的一端所期望收到的下一个序号。因此,确认序号应当时上次已成功收到数据字节序号加1。只有ACK标志为1时确认序号字段才有效。(5)发送ACK无需任何代价,因为32位的确认序号字段和ACK标志一样,总是TCP首部的一部分。因此一旦一个连接建立起来,这个字段总是被设置,ACK标志也总是被设置为1。(6)TCP为应用层提供全双工的服务。因此,连接的每一端必须保持每个方向上的传输数据序号。(7)TCP可以表述为一个没有选择确认或否认的华东窗口协议。因此TCP首部中的确认序号表示发送方已成功收到字节,但还不包含确认序号所指的字节。当前还无法对数据流中选定的部分进行确认。(8)首部长度需要设置,因为任选字段的长度是可变的。TCP首部最多60个字节。(9)6个标志位中的多个可同时设置为1◆ URG-紧急指针有效◆ ACK-确认序号有效◆ PSH-接收方应尽快将这个报文段交给应用层◆ RST-重建连接◆ SYN-同步序号用来发起一个连接◆ FIN-发送端完成发送任务(10)TCP的流量控制由连接的每一端通过声明的窗口大小来提供。窗口大小为字节数,起始于确认序号字段指明的值,这个值是接收端期望接收的字节数。窗口大小是一个16为的字段,因而窗口大小最大为65535字节。(11)检验和覆盖整个TCP报文端:TCP首部和TCP数据。这是一个强制性的字段,一定是由发送端计算和存储,并由接收端进行验证。TCP检验和的计算和UDP首部检验和的计算一样,也使用伪首部。(12)紧急指针是一个正的偏移量,黄蓉序号字段中的值相加表示紧急数据最后一个字节的序号。TCP的紧急方式是发送端向另一端发送紧急数据的一种方式。(13)最常见的可选字段是最长报文大小MMS,每个连接方通常都在通信的第一个报文段中指明这个选项。它指明本端所能接收的最大长度的报文段。二、TCP连接的建立和终止1、建立连接协议(1) 请求端发送一个SYN段指明客户打算连接的服务器的端口,隐疾初始序号(ISN),这个SYN报文段为报文段1。(2) 服务器端发回包含服务器的初始序号的SYN报文段(报文段2)作为应答。同时将确认序号设置为客户的ISN加1以对客户的SYN报文段进行确认。一个SYN将占用一个序号。(3) 客户必须将确认序号设置为服务器的ISN加1以对服务器的SYN报文段进行确认(报文段3)。这3个报文段完成连接的建立,称为三次握手。发送第一个SYN的一端将执行主动打开,接收这个SYN并发回下一个SYN的另一端执行被动打开。2、连接终止协议由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。(1) TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送(报文段4)。(2) 服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1(报文段5)。和SYN一样,一个FIN将占用一个序号。(3) 服务器关闭客户端的连接,发送一个FIN给客户端(报文段6)。(4) 客户段发回确认,并将确认序号设置为收到序号加1(报文段7)。3、连接建立的超时如果与服务器无法建立连接,客户端就会三次向服务器发送连接请求。在规定的时间内服务器未应答,则连接失败。4、最大报文段长度MSS最大报文段长度表示TCP传往另一端的最大块数据的长度。当一个连接建立时,连接的双方都要通告各自的MSS。一般,如果没有分段发生,MSS还是越大越好。报文段越大允许每个报文段传送的数据越多,相对IP和TCP首部有更高的网络利用率。当TCP发送一个 SYN时,它能将MSS值设置为外出接口的MTU长度减去IP首部和TCP首部长度。对于以太网,MSS值可达1460。如果目的地址为非本地的,MSS值通常默认为536,是否本地主要通过网络号区分。MSS让主机限制另一端发送数据报的长度,加上主机也能控制它发送数据报的长度,这将使以较小MTU连接到一个网络上的主机避免分段。5、 TCP的半关闭TCP提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力,这就是TCP的半关闭。客户端发送FIN,另一端发送对这个FIN的ACK报文段。当收到半关闭的一端在完成它的数据传送后,才发送FIN关闭这个方向的连接,客户端再对这个FIN确认,这个连接才彻底关闭。6、2MSL连接TIME_WAIT状态也称为2MSL等待状态。每个TCP必须选择一个报文段最大生存时间(MSL)。它是任何报文段被丢弃前在网络的最长时间。处理原则:当TCP执行一个主动关闭,并发回最后一个ACK,该连接必须在TIME_WAIT状态停留的时间为2MSL。这样可以让TCP再次发送最后的ACK以避免这个ACK丢失(另一端超时并重发最后的FIN)。这种2MSL等待的另一个结果是这个TCP连接在2MSL等待期间,定义这个连接的插口不能被使用。7、平静时间TCP在重启的MSL秒内不能建立任何连接,这就是平静时间。8、FIN_WAIT_2状态在FIN_WAIT_2状态我们已经发出了FIN,并且另一端也对它进行了确认。只有另一端的进程完成了这个关闭,我们这端才会从 FIN_WAIT_2状态进入TIME_WAIT状态。这意味着我们这端可能永远保持这个状态,另一端也将处于CLOSE_WAIT状态,并一直保持这个状态直到应用层决定进行关闭。9、复位报文段TCP首部的RST位是用于复位的。一般,无论合适一个报文端发往相关的连接出现错误,TCP都会发出一个复位报文段。主要情况:(1)到不存在的端口的连接请求;(2)异常终止一个连接。10、同时打开为了处理同时打开,对于同时打开它仅建立一条连接而不是两条连接。两端几乎在同时发送SYN,并进入SYN_SENT状态。当每一端收到SYN时,状态变为SYN_RCVD,同时他们都再发SYN并对收到的SYN进行确认。当双方都收到SYN及相应的ACK时,状态都变为ESTABLISHED。一个同时打开的连接需要交换4个报文段,比正常的三次握手多了一次。11、 同时关闭当应用层发出关闭命令,两端均从ESTABLISHED变为FIN_WAIT_1。这将导致双方各发送一个FIN,两个FIN经过网络传送后分别到达另一端。收到FIN后,状态由FIN_WAIT_1变为CLOSING,并发送最后的ACK。当收到最后的ACK,状态变为TIME_WAIT。同时关闭和正常关闭的段减缓数目相同。12、TCP选项每个选项的开始是1字节的kind字段,说明选项的类型。Kind=1:选项表结束(1字节) Kind=1:无操作(1字节) Kind=2:最大报文段长度(4字节) Kind=3:窗口扩大因子(4字节) Kind=8:时间戳(10字节)三、TCP的超时和重传对于每个TCP连接,TCP管理4个不同的定时器。(1) 重传定时器用于当希望收到另一端的确认。(2) 坚持定时器使窗口大小信息保持不断流动,即使另一端关闭了其接收窗口。(3) 保活定时器可检测到一个空闲连接的另一端何时崩溃或重启。(4) 2MSL定时器测量一个连接处于TIME_WAIT状态的时间。1、往返时间测量TCP超时和重传重最重要的就是对一个给定连接的往返时间(RTT)的测量。由于路由器和网络流量均会变化,因此TCP应该跟踪这些变化并相应地改变超时时间。首先TCP必须测量在发送一个带有特别序号地字节和接收到包含该字节地确认之间的RTT。2、拥塞避免算法该算法假定由于分组收到损坏引起的丢失是非常少的,因此分组丢失就意味着在源主机和目的主机之间的某处网络上发生了阻塞。有两种分组丢失的指示:发生超时和收到重复的确认。拥塞避免算法需要对每个连接维持两个变量:一个拥塞窗口cwnd和一个慢启动门限ssthresh。(1) 对一个给定的连接,初始化cwnd为1个报文段,ssthresh为65535个字节。(2) TCP输出例程的输出不能超过cwnd和接收方通告窗口的大小。拥塞避免是发送方使用的流量控制。前者是发送方感受到的网络拥塞的估计,而后者则与接收方在该连接上的可用缓存大小有关。(3) 当拥塞发生时,ssthresh被设置为当前窗口大小的一般(cwnd和接收方通告窗口大小的最小值,但最小为2个报文段)。此外,如果是超时引起了拥塞,则cwnd被设置为1个报文段。(4) 当新的数据被对方确认时,就增加cwnd,但增加的方法依赖与是否正在进行慢启动或拥塞避免。如果cwnd小于或等于ssthresh,则正在进行慢启动,否则正在进行拥塞避免。3、快速重传和快速恢复算法如果我们一连串收到3个或以上的重复ACK,就非常可能是一个报文段丢失了。于是我们就重传丢失的数据报文段,而无需等待超时定时器溢出。(1) 当收到第3个重复的ACK时,将ssthresh设置为当前拥塞窗口cwnd的一半,重传丢失的报文段,设置cwnd为ssthresh加上3倍的报文段大小。(2) 每次收到另一个重复的ACK时,cwnd增加1个报文段大小并发送一个1个分组,如果允许的话。(3)当下一个确认新数据的ACK到达时,设置cwnd为ssthresh,这个ACK应该时在进行重传后的一个往返时间内对步骤1重重传的确认。另外,这个 ACK也应该是对丢失的分组和收到的第一个重复的ACK之间的所有中间报文段的确认。4、 ICMP差错TCP如何处理一个给定的连接返回的ICMP差错。TCP能够遇到的最常见的ICMP差错就是源站抑制、主机不可达和网络不可达。(1) 一个接收到的源站抑制引起拥塞窗口cwnd被置为1个报文段大小来发起慢启动,但是慢启动门限ssthresh没有变化,所以窗口将打开直到它开放了所有的通路或者发生了拥塞。(2) 一个接收到的主机不可达或网络不可达实际都被忽略,因为这两个差错都被认为是短暂现象。TCP试图发送引起该差错的数据,尽管最终有可能会超时。5、重新分组:当TCP超时并重传时,它并不一定要重传同样的报文段,相反,TCP允许进行重新分组而发送一个较大的报文段。这是允许的,因为TCP是使用字节序号而不是报文段序号来进行识别它所要发送的数据和进行确认。四、TCP的坚持定时器ACK的传输并不可靠,也就是说,TCP不对ACK报文段进行确认,TCP只确认那些包含数据的ACK报文段。为了防止因为ACK报文段丢失而双方进行等待的问题,发送方用一个坚持定时器来周期性地向接收方查询。这些从发送方发出地报文段称为窗口探查。五、TCP的保活定时器如果一个给定的连接在2小时内没有任何动作,那么服务器就向客户发送一个探查报文段。客户主机必须处于以下4个状态之一。(1) 客户主机依然正常运行,并从服务器可达。客户的TCP响应正常,而服务器也知道对方的正常工作的。服务器在2小时内将保活定时器复位。(2) 客户主机已经崩溃,并且关闭或者正在重新启动。在任何一种情况下,客户的TCP都没有响应。服务器将不能收到对探查的响应,并在75秒后超时。总共发送10个探查,间隔75秒。(3) 客户主机崩溃并已经重新启动。这是服务器将收到一个对其保活探查的响应,但这个响应是一个复位,使得服务器终止这个连接。(4) 客户主机正常运行,但是从服务器不可达。六、TCP的一些性能1、 路径MTU发现:TCP的路径MTU发现按如下方式进行:在连接建立时,TCP使用输出接口或对段声明的MSS中的最下MTU作为其实的报文段大小。路径MTU发现不允许TCP超过对端声明的MSS。如果对端没有指定一个MSS,则默认为536。一旦选定了起始的报文段大小,在该连接上的所有被TCP发送的IP数据报都将被设置DF位。如果中间路由器需要对一个设置了DF标志的数据报进行分片,它就丢弃这个数据报,并产生一个ICMP的“不能分片”差错。如果收到这个ICMP差错,TCP就减少段大小并进行重传。如果路由器产生的是一个较新的该类ICMP差错,则报文段大小被设置位下一跳的MTU减去 IP和TCP的首部长度。如果是一个较旧的该类ICMP差错,则必须尝试下一个可能的最小MTU。2、 长肥管道一个连接的容量=带宽X时延(RTT)。具有大的带宽时延乘积的网络称为长肥网络(LFN)。一个运行在LFN的TCP连接称为长肥管道。管道可以被水平拉长(一个长的RTT),或被垂直拉高(较高的带宽),或两个方向拉伸。3、窗口扩大选项:窗口扩大选项使TCP的窗口定义从16位增加到32位,这并不是通过修改TCP首部来实现的,TCP首部仍然使用16位,而是通过定义一个选项实现对16位的扩大操作来完成的。4、时间戳选项: 时间戳选项使发送方在每个报文段中放置一个时间戳值。接收方在确认中返回这个数值,从而允许发送方为每一个收到的ACK计算RTT。
      TCP采用哪些机制来实现可靠数据传输、流控和拥塞控制?

      网络--三次握手

      由高到低应用层是体系结构中的最高层,直接为用户的应用进程(正在运行的程序)提供服务 。在因特网中的应用层协议很多,如支持万维网应用的HTTP协议,支持文件传输的FTP协议,支持电子邮件的SMTP协议等等。运输层的任务是负责向两个主机中进程之间的通信提供服务。由于一个主机可同时运行多个进程,因此运输层有复用和分用的功能。复用就是多个应用层进程可以同时使用下面运输层的服务,分用则是运输层把收到的信息分别交付给上面应用层中的相应的进程。运输层主要使用两种协议:网络层负责为分组交换网上的不同主机提供通信服务。在发送数据的时候,网络层把运输层产生的报文段或者用户数据报封装成分组或包进行传送。在TCP/IP体系中,由于网络层使用IP协议,因此分组也叫IP数据报,或简称数据报。无论在哪一层传送的数据单元,习惯上都可以笼统地用“分组”来表示因特网是一个很大的互联网,它由大量的异构网络通过路由器(router)相连接。因特网主要的网络层协议是无连接的网际协议IP和许多种路由选择协议,所以因特网的网络层也叫网际层或者IP层。简称链路层。两个主机之间的数据传输总是在一段一段的链路上传送的,也就是说,在两个相邻结点之间(主机和路由器之间或者两个路由器之间)传送数据是直接传送的(点对点)。这时就需要使用专门的链路层的协议。 在两个相邻结点之间传送数据时,数据链路层把网络层交下来的IP数据报组装成帧(frame),在两个相邻结点间的链路上“透明”的传送帧中的数据。每一帧包括数据和必要的控制信息(如同步信息、地址信息、差错控制等)。典型的帧长是几百字节到一千多字节。透明:某一个实际存在的事物看起来却好像不存在一样。在接收数据时,控制信息使接收端能够知道一个帧从哪个比特开始和到哪个比特结束,还使接收端能够检测到所收到的帧中有无差错,如发现错误,数据链路层就简单地丢弃这个出了差错的帧,以免继续浪费网络资源。如需改错,则交给运输层的TCP协议完成。在物理层上传输数据的单位是比特。物理层的任务就是透明地传送比特流。在因特网所使用的各种协议中,最重要的和最著名的就是TCP和IP两个协议。现在人们经常提起的TCP/IP并不一定是单指TCP和IP这两个具体的协议,而是表示因特网所使用的整个TCP/IP协议族(Protocol suite)TCP运输连接的建立和释放是每一次面向连接的通信中必不可少的过程。因此,运输连接就有三个阶段:连接建立、数据传送和连接释放。运输连接的管理就是使运输连接的建立和释放都能正常地进行。在TCP建立连接的过程中要解决三个问题:TCP连接的建立采用客户服务器方式。主动发起连接建立的应用进程叫做客户(Client),被动等待连接建立的应用程序叫做服务器(Server)。假设主机A运行的是TCP客户程序,主机B运行TCP服务器程序。最初两端的TCP进程都处在CLOSED(关闭)状态。A主动打开连接,而B被动打开连接。B的TCP服务器进程先创建传输控制块TCB,准备接受客户进程的连接请求。然后服务器就处于LISTEN(收听)状态,等待客户的连接请求,如有,即作出反应。A的TCP客户进程也是首先创建传输控制模块TCB,然后向B发出连接请求报文段,——>首部中的同步位SYN = 1,同时选择一个初始序号seq = x,——>TCP客户进入SYN-SENT(同步以发送)状态。注:TCP规定,SYN报文段(即SYN = 1的报文段)不能携带数据,但要消耗掉一个序号。B收到连接请求报文段后,如同意建立连接,则向A发送确认。——>在确认报文段中把SYN位和ACK位都置1,确认号是ack = x+1,同时也为自己选择一个初始序号seq = y。(注:该确认报文段也不能携带数据,但同样要消耗掉一个序号。)——>这时,TCP服务器进程进入SYN-RCVD(同步收到)状态。TCP客户进程收到B的确认后,还要向B给出确认。——>确认报文段的ACK置1,确认号ack = y+1,而自己的序号seq = x + 1(注:TCP规定,ACK报文段可以携带数据,但如果不携带数据则不消耗序号,在这种情况下,下一个数据报文段的序号仍是seq = x +1。)——>这时,TCP连接已经建立,A进入ESTABLISHED(已建立连接)状态。当B收到A的确认后也进入ESTABLISHED状态。主要是为了防止已失效的连接请求报文段突然又传送到了服务器主机B假定A发出连接请求,但因连接请求报文丢失而未收到确认,于是A再重传一次连接请求,后来收到了确认,建立了连接,数据传输完毕后就释放了连接。这个过程中,A共发送了两个请求报文段,其中第一个丢失,第二个到达了B。于是就可能有“已失效的连接请求报文段产生”:假定一种异常的情况,即A发出的第一个连接请求报文段并没有丢失,而是在某些网络结点长时间的滞留了,以致延误到第二个请求报文段连接释放以后的某个时间才到达B。本来这是一个已失效的报文段。但B收到此失效的连接请求报文段后,就误以为A又一次发出了一次新的连接请求,于是就向A发送确认报文段,同意建立连接请求。假如不采用三次握手,那么只要B发出确认,新的连接就建立了。由于现在A并没有发出建立连接的请求,所以不会理睬B的确认,也不会向B发送数据,但是B却以为新的运输连接已经建立了,并一直等待A发来数据。于是,B的许多资源就这样被白白浪费了。采用三次握手,A 不会向 B 的确认发出确认,B由于收不到确认,就知道A并没有要求要建立连接。
      网络--三次握手

      tcp连接状态详解

      unix的哲学是一切皆文件,可以把socket看成是一种特殊的文件,而一些socket函数就是对其进行的操作api(读/写IO、打开、关闭)。我们知道普通文件的打开操作(open)返回一个文件描述字,与之类似,socket()用于创建一个socket描述符(socket descriptor),它唯一标识一个socket。当我们调用socket创建一个socket时,返回的socket描述字它存在于协议族(address family,AF_XXX)空间中,但没有一个具体的地址。如果想要给它赋值一个地址,就必须调用bind()函数,sockfd即socket描述字,它是通过socket()函数创建了,唯一标识一个socket。bind()函数就是将给这个描述字绑定一个名字。在将一个地址绑定到socket的时候,需要先将主机字节序转换成为网络字节序,而不要假定主机字节序跟网络字节序一样使用的是Big-Endian。由于这个问题曾引发过不少血案,谨记对主机字节序不要做任何假定,务必将其转化为网络字节序再赋给socket。这里的主机字节序就是我们平常说的大端和小端模式:不同的CPU有不同的字节序类型,这些字节序是指整数在内存中保存的顺序,这个叫做主机序。引用标准的Big-Endian和Little-Endian的定义如下:listen函数的第一个参数即为要监听的socket描述字,第二个参数为socket可以接受的排队的最大连接个数。listen函数表示等待客户的连接请求。connect函数的第一个参数即为客户端的socket描述字,第二参数为服务器的socket地址,第三个参数为socket地址的长度。客户端通过调用connect函数来建立与TCP服务器的连接。TCP服务器端依次调用socket()、bind()、listen()之后,就会监听指定的socket地址了。TCP客户端依次调用socket()、connect()之后就向TCP服务器发送连接请求。TCP服务器监听到这个请求之后,就会调用accept()函数去接收请求,这样连接就建立好了(在connect之后就建立好了三次连接),之后就可以开始进行类似于普通文件的网络I/O操作了。如果accpet成功,那么其返回值是由内核自动生成的一个全新的描述字,代表与客户的TCP连接。accept的第一个参数为服务器的socket描述字,是服务器开始调用socket()函数生成的,称为监听socket描述字;而accept函数返回的是已连接的socket描述字。一个服务器通常通常仅仅只创建一个监听socket描述字,它在该服务器的生命周期内一直存在。内核为每个由服务器进程接受的客户连接创建了一个已连接socket描述字,当服务器完成了对某个客户的服务,相应的已连接socket描述字就被关闭。read函数是负责从fd中读取内容.当读成功时,read返回实际所读的字节数,如果返回的值是0表示已经读到文件的结束了,小于0表示出现了错误。如果错误为EINTR说明读是由中断引起的,如果是ECONNREST表示网络连接出了问题。write函数将buf中的nbytes字节内容写入文件描述符fd.成功时返回写的字节数。失败时返回-1,并设置errno变量。 在网络程序中,当我们向套接字文件描述符写时有俩种可能。1)write的返回值大于0,表示写了部分或者是全部的数据。2)返回的值小于0,此时出现了错误在服务器与客户端建立连接之后,会进行一些读写操作,完成了读写操作就要关闭相应的socket描述字,类似于操作完打开的文件要调用fclose关闭打开的文件。close一个TCP socket的缺省行为时把该socket标记为已关闭,然后立即返回到调用进程。该描述字不能再由调用进程使用,也就是说不能再作为read或write的第一个参数close操作只是使相应socket描述字的引用计数-1,只有当引用计数为0的时候,才会触发TCP客户端向服务器发送终止连接请求。我们知道tcp建立连接要进行“三次握手”,即交换三个分组。大致流程如下:客户端向服务器发送一个SYN J服务器向客户端响应一个SYN K,并对SYN J进行确认ACK J+1客户端再想服务器发一个确认ACK K+1socket中TCP的四次握手释放连接详解某个应用进程首先调用close主动关闭连接,这时TCP发送一个FIN M;另一端接收到FIN M之后,执行被动关闭,对这个FIN进行确认。一段时间之后,服务端调用close关闭它的socket。这导致它的TCP也发送一个FIN N;接收到这个FIN的源发送端TCP对它进行确认,这样每个方向上都有一个FIN和ACK。为什么要三次握手由于tcp连接是全双工的,存在着双向的读写通道,每个方向都必须单独进行关闭。当一方完成它的数据发送任务后就可以发送一个FIN来终止这个方向的连接。收到FIN只意味着这个方向上没有数据流动,但并不表示在另一个方向上没有读写,所以要双向的读写关闭需要四次握手,3. time_wait状态如何避免?首先服务器可以设置SO_REUSEADDR套接字选项来通知内核,如果端口忙,但TCP连接位于TIME_WAIT状态时可以重用端口。在一个非常有用的场景就是,如果你的服务器程序停止后想立即重启,而新的套接字依旧希望使用同一端口,此时SO_REUSEADDR选项就可以避免TIME_WAIT状态。1.客户端连接服务器的80服务,这时客户端会启用一个本地的端口访问服务器的80,访问完成后关闭此连接,立刻再次访问服务器的80,这时客户端会启用另一个本地的端口,而不是刚才使用的那个本地端口。原因就是刚才的那个连接还处于TIME_WAIT状态。2.客户端连接服务器的80服务,这时服务器关闭80端口,立即再次重启80端口的服务,这时可能不会成功启动,原因也是服务器的连接还处于TIME_WAIT状态。实战分析:状态描述:CLOSED:无连接是活动的或正在进行LISTEN:服务器在等待进入呼叫SYN_RECV:一个连接请求已经到达,等待确认SYN_SENT:应用已经开始,打开一个连接ESTABLISHED:正常数据传输状态FIN_WAIT1:应用说它已经完成FIN_WAIT2:另一边已同意释放ITMED_WAIT:等待所有分组死掉CLOSING:两边同时尝试关闭TIME_WAIT:另一边已初始化一个释放LAST_ACK:等待所有分组死掉命令解释:如何尽量处理TIMEWAIT过多?编辑内核文件/etc/sysctl.conf,加入以下内容:net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。net.ipv4.tcp_fin_timeout 修改系默认的 TIMEOUT 时间然后执行 /sbin/sysctl -p 让参数生效./etc/sysctl.conf是一个允许改变正在运行中的Linux系统的接口,它包含一些TCP/IP堆栈和虚拟内存系统的高级选项,修改内核参数永久生效。简单来说,就是打开系统的TIMEWAIT重用和快速回收。本文主要讲述了socket的主要api,以及tcp的连接过程和其中各个阶段的连接状态,理解这些是更深入了解tcp的基础!
      tcp连接状态详解

      TCP协议总结

      Transmission Control Protocol,传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议TCP协议的目的是:在不可靠传输的IP层之上建立一套可靠传输的机制。TCP的可靠只是对于它自身来说的, 甚至是对于socket接口层, 两个系统就不是可靠的了, 因为发送出去的数据, 没有确保对方真正的读到(所以要在业务层做重传和确认机制)。可靠传输的第一要素是确认, 第二要素是重传, 第三要素是顺序。 任何一个可靠传输的系统, 都必须包含这三个要素。数据校验也是必要的。传输是一个广义的概念, 不局限于狭义的网络传输, 应该理解为通信和交互. 任何涉及到通信和交互的东西, 都可以借鉴TCP的思想。无论是在UDP上实现可靠传输或者创建自己的通信系统,无论这个系统是以API方式还是服务方式,只要是一个通信系统,就要考虑这三个要素。SeqNum的增加是和传输的字节数相关的。上图中,三次握手后,来了两个Len:1440的包,而第二个包的SeqNum就成了1441。然后第一个ACK回的是1441(下一个待接收的字节号),表示第一个1440收到了。网络上的传输是没有连接的,包括TCP也是一样的。而TCP所谓的“连接”,其实只不过是在通讯的双方维护一个“连接状态”,让它看上去好像有连接一样。所以,TCP的状态变换是非常重要的。查看各种状态的数量ss -ant | awk '{++s[$1]} END {for(k in s) print k,s[k]}'通过三次握手完成连接的建立三次握手的目的是交换通信双方的初始化序号,以保证应用层接收到的数据不会乱序,所以叫SYN(Synchronize Sequence Numbers)。ISN是不能hard code的,不然会出问题的。比如:如果连接建好后始终用1来做ISN,如果client发了30个segment过去,但是网络断了,于是client重连,又用了1做ISN,但是之前连接的那些包到了,于是就被当成了新连接的包,此时,client的Sequence Number可能是3,而Server端认为client端的这个号是30了。全乱了。RFC793中说,ISN会和一个假的时钟绑在一起,这个时钟会在每4微秒对ISN做加一操作,直到超过232,又从0开始。这样,一个ISN的周期大约是4.55个小时。因为,我们假设我们的TCP Segment在网络上的存活时间不会超过Maximum Segment Lifetime(MSL),所以,只要MSL的值小于4.55小时,那么,我们就不会重用到ISN。如果Server端接到了Clien发的SYN后回了SYN-ACK,之后Client掉线了,Server端没有收到Client返回的ACK,那么,这个连接就处于一个中间状态,即没成功,也没失败。于是,Server端如果在一定时间内没有收到的ACK会重发SYN-ACK。在Linux下,默认重试次数为5次,重试的间隔时间从1s开始每次都翻番,5次的重试时间间隔为1s, 2s, 4s, 8s, 16s,总共31s,第5次发出后还要等32s都知道第5次也超时了,所以,总共需要 1s + 2s + 4s+ 8s+ 16s + 32s = 26 -1 = 63s,TCP才会断开这个连接。客户端给服务器发了一个SYN后,就下线了,于是服务器需要默认等63s才会断开连接,这样,攻击者就可以把服务器的SYN连接的队列耗尽,让正常的连接请求不能处理。于是,Linux下给了一个叫tcp_syncookies的参数来应对这个事:当SYN队列满了后,TCP会通过源地址端口、目标地址端口和时间戳打造出一个特别的Sequence Number发回去(又叫cookie),此时服务器并没有保留客户端的SYN包。如果是攻击者则不会有响应,如果是正常连接,则会把这个SYN Cookie发回来,然后服务端可以通过cookie建连接(即使你不在SYN队列中)。千万别用tcp_syncookies来处理正常的大负载的连接的情况。因为sync cookies是妥协版的TCP协议,并不严谨。应该调整三个TCP参数:tcp_synack_retries减少重试次数,tcp_max_syn_backlog增大SYN连接数,tcp_abort_on_overflow处理不过来干脆就直接拒绝连接因为TCP是全双工的,因此断开连接需要4次挥手,发送方和接收方都需要发送Fin和Ack。如果两边同时断连接,那就会就进入到CLOSING状态,然后到达TIME_WAIT状态。指的是报文段的最大生存时间,如果报文段在网络中活动了MSL时间,还没有被接收,那么会被丢弃。关于MSL的大小,RFC 793协议中给出的建议是两分钟,不过实际上不同的操作系统可能有不同的设置,以Linux为例,通常是半分钟,两倍的MSL就是一分钟,也就是60秒主动关闭的一方会进入TIME_WAIT状态,并且在此状态停留两倍的MSL时长。由于TIME_WAIT的存在,大量短连接会占有大量的端口,造成无法新建连接。主动关闭的一方发出 FIN包,被动关闭的一方响应ACK包,此时,被动关闭的一方就进入了CLOSE_WAIT状态。如果一切正常,稍后被动关闭的一方也会发出FIN包,然后迁移到LAST_ACK状态。CLOSE_WAIT状态在服务器停留时间很短,如果你发现大量的 CLOSE_WAIT状态,那么就意味着被动关闭的一方没有及时发出FIN包。TCP要保证所有的数据包都可以到达,所以,必需要有重传机制。接收端给发送端的Ack确认只会确认最后一个连续的包,比如,发送端发了1,2,3,4,5一共五份数据,接收端收到了1,2,于是回ack 3,然后收到了4(注意此时3没收到),此时的TCP会怎么办?我们要知道,因为正如前面所说的,SeqNum和Ack是以字节数为单位,所以ack的时候,不能跳着确认,只能确认最大的连续收到的包,不然,发送端就以为之前的都收到了但总体来说都不好。因为都在等timeout,timeout可能会很长不以时间驱动,而以数据驱动重传如果包没有连续到达,就ack最后那个可能被丢了的包,如果发送方连续收到3次相同的ack,就重传Selective Acknowledgment, 需要在TCP头里加一个SACK的东西,ACK还是Fast Retransmit的ACK,SACK则是汇报收到的数据碎版,在发送端就可以根据回传的SACK来知道哪些数据到了,哪些没有收到重复收到数据的问题,使用了SACK来告诉发送方有哪些数据被重复接收了经典算法:Karn/Partridge算法,Jacobson/Karels算法TCP必需要知道网络实际的数据处理带宽或是数据处理速度,这样才不会引起网络拥塞,导致丢包Advertised-Window:接收端告诉发送端自己还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来接收端LastByteRead指向了TCP缓冲区中读到的位置,NextByteExpected指向的地方是收到的连续包的最后一个位置,LastByteRcved指向的是收到的包的最后一个位置,我们可以看到中间有些数据还没有到达,所以有数据空白区。发送端的LastByteAcked指向了被接收端Ack过的位置(表示成功发送确认),LastByteSent表示发出去了,但还没有收到成功确认的Ack,LastByteWritten指向的是上层应用正在写的地方。接收端在给发送端回ACK中会汇报自己的AdvertisedWindow = MaxRcvBuffer – LastByteRcvd – 1;收到36的ack,并发出了46-51的字节如果Window变成0了,发送端就不发数据了如果发送端不发数据了,接收方一会儿Window size 可用了,怎么通知发送端呢:TCP使用了Zero Window Probe技术,缩写为ZWP,也就是说,发送端在窗口变成0后,会发ZWP的包给接收方,让接收方来ack他的Window尺寸,一般这个值会设置成3次,每次大约30-60秒。如果3次过后还是0的话,有的TCP实现就会发RST把链接断了。如果你的网络包可以塞满MTU,那么你可以用满整个带宽,如果不能,那么你就会浪费带宽。避免对小的window size做出响应,直到有足够大的window size再响应。如果这个问题是由Receiver端引起的,那么就会使用David D Clark’s 方案。在receiver端,如果收到的数据导致window size小于某个值,可以直接ack(0)回sender,这样就把window给关闭了,也阻止了sender再发数据过来,等到receiver端处理了一些数据后windows size大于等于了MSS,或者receiver buffer有一半为空,就可以把window打开让send 发送数据过来。如果这个问题是由Sender端引起的,那么就会使用著名的 Nagle’s algorithm。这个算法的思路也是延时处理,他有两个主要的条件:1)要等到 Window Size >= MSS 或是 Data Size >= MSS,2)等待时间或是超时200ms,这两个条件有一个满足,他才会发数据,否则就是在攒数据。TCP_CORK是禁止小包发送,而Nagle算法没有禁止小包发送,只是禁止了大量的小包发送TCP不是一个自私的协议,当拥塞发生的时候,要做自我牺牲拥塞控制的论文请参看 《Congestion Avoidance and Control》主要算法有:慢启动,拥塞避免,拥塞发生,快速恢复,TCP New Reno,FACK算法,TCP Vegas拥塞控制算法TCP网络协议及其思想的应用TCP 的那些事儿(上)TCP 的那些事儿(下)tcp为什么是三次握手,为什么不是两次或四次?记一次TIME_WAIT网络故障再叙TIME_WAITtcp_tw_recycle和tcp_timestamps导致connect失败问题tcp短连接TIME_WAIT问题解决方法大全(1)- 高屋建瓴tcp短连接TIME_WAIT问题解决方法大全(2)- SO_LINGERtcp短连接TIME_WAIT问题解决方法大全(3)- tcp_tw_recycletcp短连接TIME_WAIT问题解决方法大全(4)- tcp_tw_reusetcp短连接TIME_WAIT问题解决方法大全(5)- tcp_max_tw_bucketsTCP的TIME_WAIT快速回收与重用浅谈CLOSE_WAIT又见CLOSE_WAITPHP升级导致系统负载过高问题分析Coping with the TCP TIME-WAIT state on busy Linux servers
      TCP协议总结

      本文由 在线网速测试 整理编辑,转载请注明出处,原文链接:https://www.wangsu123.cn/news/60491.html

          热门文章

          文章分类