SEO教程

SEO教程

Products

当前位置:首页 > SEO教程 >

如何有效利用猎头网站策划公司的广告费来吸引潜在客户?

96SEO 2026-02-19 11:13 9


确认应答号#xf…TCP

包传给接收端主机每发送一次数据就「累加」一次该「数据字节数」的大小。

如何有效利用猎头网站策划公司的广告费来吸引潜在客户?

用来解决网络包乱序问题。

确认应答号指下一次「期望」收到的数据的序列号发送端收到这个确认应答以后可以认为在这个序号以前的数据都已经被正常接收。

用来解决丢包的问题。

控制位

时表示希望建立连接并在其「序列号」的字段进行序列号初始值的设定。

FIN该位为

时表示今后不会再有数据发送希望断开连接。

当通信结束希望断开连接时通信双方的主机之间就可以相互交换

FIN

层是「不可靠」的它不保证网络包的交付、不保证网络包的按序交付、也不保证网络包中的数据的完整性。

为了能够可靠传递就需要上层传输层的

TCP

是一个工作在传输层的可靠数据传输的服务它能确保接收端接收的网络包是无损坏、无间隔、非冗余和按序的。

TCP

是面向连接的、可靠的、基于字节流的传输层通信协议。

面向连接就是指一定是「一对一」的连接不像

UDP

报文有序即使后面的报文先到达也不会给应用层而是等待同时重复报文会自动丢弃。

地址和端口号组成序列号之前已经学习就是解决乱序问题窗口大小就是用来流量控制。

TCP

连接都要占用一定内存操作系统的内存是有限的如果内存资源被占满后会发生

那么为什么有

地址寻找主机传输层通过端口来寻址找到同一计算机中通信的不同应用程序。

端口号就是为了区分同一主机上不同的应用程序的数据包。

所以说TCP、UDP

TCP

最后把报文发送给服务端这次报文可以携带客户到服务端的数据之后客户端处于

ESTABLISHED

首要原因是为了防止旧的重复连接初始化造成混乱。

如果客户端发了旧的

SYN

两次握手就无法阻止历史连接因为此时服务端没有中间状态给客户端来阻止历史连接导致服务端可能建立一个历史连接造成资源浪费。

要解决这种现象最好就是在服务端发送数据前也就是建立连接之前要阻止掉历史连接这样就不会造成资源浪费而要实现这个功能就需要三次握手。

同步双方初始序列号

都必须维护一个「序列号」因为依靠序列号接收方可以去除重复数据接收方可以以此按序接收通过序列号来标识已经被接收到的报文通过

ACK

报文已被服务端成功接收同理服务端发送「初始序列号」给客户端的时候依然也要得到客户端的应答回应这样一来一回才能确保双方的初始序列号能被可靠的同步。

通过四次握手也就是两次互相发

SYN

如之前所说只有两次握手那么就会有历史连接因为服务端不确定客户端是否收到

ACK

防止历史报文被下一个相同四元组连接接收主要安全性防止相同序列号

TCP

之后客户端传资源超时服务端断电重启那么久会在重启的时候建立失效进而导致服务端回发

RST

CLOSED。

然后如果再次建立连接此时序列号是一样的而上一次连接发送的那个报文正好抵达服务端那么现在的序列号没变就会导致数据传递是有效的那么服务端就会正常接收导致数据产生混乱。

如果序列号不一样那么第二次连接生效的序列号就发生了改变也就不会导致接收成功了会把该报文直接丢弃。

初始序列号随机产生

tcp_syn_retries内核参数控制这个参数是可以自定义的默认值一般是

tcp_syn_retries

所以如果第二次丢失对第一次握手的确认报文就没有了客户端就会触发超时重传机制重传

SYN

的确认报文所以当第三次握手丢失了如果服务端那一方迟迟收不到这个确认报文就会触发超时重传机制重传

SYN-ACK

应答久而久之就会占满服务端的半连接队列使得服务端不能为正常用户服务。

SYN

ACK因此通常被称为四次挥手。

这里一点需要注意是主动关闭连接的才有

TIME_WAIT

时仅仅表示客户端不再发送数据了但是还能接收数据。

服务端收到客户端的

FIN

应答报文而服务端可能还有数据需要处理和发送等服务端不再发送数据时才发送

FIN

函数关闭连接指定了只关闭发送方向而接收方向并没有关闭那么意味着主动关闭方还是可以接收数据的。

此时如果主动关闭方一直没收到第三次挥手那么主动关闭方的连接将会一直处于

FIN_WAIT2

函数关闭连接。

此时内核是没有权利替代进程关闭连接必须由进程主动调用

close

Lifetime报文最大生存时间它是任何报文在网络上存在的最长时间超过这个时间报文将被丢弃。

因为

TCP

网络中可能存在来自发送方的数据包当这些发送方的数据包被接收方处理后又会向对方发送响应所以一来一回需要等待

2MSL时长

这其实是相当于至少允许报文丢失一次。

而起始计算的时间是从客户端接收到

FIN

防止历史连接中的数据被后面相同四元组的连接错误的接收保证「被动关闭连接」的一方能被正确的关闭。

TCP

0。

初始序列号是客户端和服务端会各自生成的一个随机数可被视为一个

微秒加

小时。

两者并不是无限递增的会发生回绕为初始值的情况这意味着无法根据序列号来判断新老数据。

SEQ

报文就会抵达客户端该序列号又刚好落在客户端接收窗口内就会使得客户端正常接收导致数据错乱。

TCP

时长这个时间足以让两个方向上的数据包都被丢弃使得原来连接的数据包在网络中都自然消失再出现的数据包一定都是新建立连接所产生的。

TIME-WAIT

能让被动关闭方接收从而帮助其正常关闭。

如果客户端主动关闭方最后一次

ACK

资源、线程资源等第二是占用端口资源端口资源也是有限的一般可以开启的端口为

TIME_WAIT

PORT」都一样的服务端发起连接了但已经被使用的端口还是可以继续对另一个服务端发起连接的。

四元组来定位客户端端口一样并不影响连接

TIME_WAIT

字节字段用来保存最近一次接收对方发送到达数据的时间。

由于引入了时间戳我们在前面提到的

2MSL

net.ipv4.tcp_max_tw_buckets这个值默认为

18000当系统中处于

so_linger,sizeof(so_linger));如果服务端要避免过多的

TIME_WAIT

状态的连接就永远不要主动断开连接让客户端去断开由分布在各处的客户端去承受

服务器出现大量

状态是主动关闭连接方才会出现的状态也就是说现在是服务器主动断开很多

TCP

Keep-Alive都是由服务端主动关闭连接那么此时服务端上就会出现

TIME_WAIT

响应后服务端也会主动关闭连接。

在服务端主动关闭连接的情况下只要调用一次

close()

Keep-Alive。

**任意一方没开都会导致服务端在处理完一个

HTTP

长连接上最大能处理的请求数量当超过最大限制时就会主动关闭连接。

如果达到这个参数设置的最大值时则

nginx

状态是「被动关闭方」才会有的状态而且如果「被动关闭方」没有调用

close

状态的连接的时候通常都是代码的问题这时候我们需要针对具体的代码一步一步的进行排查和定位主要分析的方向就是服务端为什么没有调用

建立连接后客户端故障

保活机制会开始作用每隔一个时间间隔发送一个探测报文该探测报文包含的数据非常少如果连续几个探测报文都没有得到响应则认为当前的

TCP

保活时间对端主机宕机并重启此时对端可以响应但是连接已经失效了只会返回

FIN

但这个时间是很长的所以可以自己定义一个时间来实现这个功能web

服务软件一般都会提供

秒内都没有再发起新的请求定时器的时间一到就会触发回调函数来释放该连接。

已经建立连接服务端进程崩溃

报文后续的挥手过程也都是在内核完成并不需要进程的参与所以即使服务端的进程退出了还是能与客户端完成

TCP

会被放在已排队等候的其他已接收的数据之后这就意味着服务端需要处理这种异常情况因为

EOF

客户端是可以自己连自己的形成连接TCP自连接也可以两个客户端同时向对方发出请求建立连接TCP同时打开这两个情况都有个共同点就是没有服务端参与也就是没有

listen就能

是通过序列号、确认应答、重发控制、连接管理以及窗口控制等机制实现可靠性传输的。

重传机制

指的是数据发送时刻到接收到确认的时刻的差值也就是包的往返时间。

超时重传时间是以

RTO

如果已经重发再度出发超时重发这时候超时的时间就会加倍。

两次超时就说明网络环境差不宜频繁反复发送。

快速重传

但是虽然解决了超时时间的问题还是存在着重传时是重传一个还是重传所有的问题。

为了解决不知道该重传哪些

TCP

的东西它可以将已收到的数据的信息发送给「发送方」这样发送方就可以知道哪些数据收到了哪些数据没收到知道了这些信息就可以只重传丢失的数据。

ACK

的头部信息接收到并缓存下来的接收缓冲区查看丢失的数据然后只重发丢失数据即可。

如果要支持

相同会触发快速重传如果之后收到了延时的包此时就会再回一个这一时刻收到的那个重复的包SACK通知发送方这个是网络延时问题。

Linux

引入了窗口这个概念。

即使在往返时间较长的情况下它也不会降低网络通信的效率。

那么有了窗口就可以指定窗口大小窗口大小就是指无需等待确认应答而可以继续发送数据的最大值。

ACK

来确认应答判断是否收到数据。

这个模式就叫累计确认或者累计应答。

TCP

Window也就是窗口大小。

这个字段是接收端告诉发送端自己还有多少缓冲区可以接收数据。

于是发送端就可以根据这个接收端的处理能力来发送数据而不会导致接收端处理不过来。

所以通常窗口大小是由接收方决定的。

只有在窗口还有剩余的情况下发送方才可以继续发送如果收到了应答那么就会滑动窗口也就是又有可以发送的数据了这时就会继续发送直到窗口再度耗尽。

TCP

滑动窗口方案使用三个指针来跟踪在四个传输类别中的每一个类别中的字节。

其中两个指针是绝对指针指特定的序列号一个是相对指针需要做偏移。

SND.WND

同时注意接收窗口的大小是约等于发送窗口的大小的。

滑动窗口并不是一成不变的。

流量控制

提供一种机制可以让「发送方」根据「接收方」的实际接收能力控制发送的数据量这就是所谓的流量控制。

操作系统缓冲区与滑动窗口

实际上发送窗口和接收窗口中所存放的字节数都是放在操作系统内存缓冲区中的而操作系统的缓冲区会被操作系统调整。

这种调整可以看下面两个图的例子来感受一下就不配说明性的文字了图已经比较清晰的展示出来了

时发送方实际上会定时发送窗口探测报文以便知道接收方的窗口是否发生了改变这个内容后面会进一步学习。

上图的情况就会出现最后发送端的窗口出现负值。

为了规避这种情况TCP

规定是不允许同时减少缓存又收缩窗口的而是采用先收缩窗口过段时间再减少缓存这样就可以避免了丢包情况。

窗口关闭

如果接收方来不及取走窗口数据那么就会导致窗口的减小如果接收方腾出几个字节并告诉发送方现在有几个字节的窗口而发送方会义无反顾地发送这几个字节这就是糊涂窗口综合症。

也就是说在接收方来不及取出数据的时候就会告知窗口大小然后每次循环就会导致最后窗口越来越小每次只能发送一点点数据。

那么为了解决这个问题一般就是同时解决两个方面接收方不通告小窗口发送方避免发送小数据。

当**「窗口大小」小于

MSS或者接收方缓存空间超过一半可用再打开窗口让发送方发送数据。

发送方策略

算法该算法的思路是延时处理只有满足下面两个条件中的任意一个条件才可以发送数据

条件一要等到窗口大小

流量控制是避免「发送方」的数据填满「接收方」的缓存但是并不知道网络的中发生了什么。

TCP

在网络出现拥堵时如果继续发送大量数据包可能会导致数据包时延、丢失等这时

TCP

就会重传数据但是一重传就会导致网络的负担更重于是会导致更大的延迟以及更多的丢包这个情况就会进入恶性循环被不断地放大…

所以为了在「发送方」调节所要发送数据的量定义了一个叫做「拥塞窗口」的概念。

拥塞窗口

cwnd

是发送方维护的一个的状态变量它会根据网络的拥塞程度动态变化的。

发送窗口

是约等于的关系那么由于加入了拥塞窗口的概念后此时发送窗口的值是swnd

min(cwnd,

1/cwnd。

也就是说进入拥塞避免算法发包的个数变成了线性增长。

拥塞发生

拥塞发生后就会触发重传机制一般而言有两个一个是超时重传一个是快速重传。

两者的拥塞发送算法不同。

超时重传

ACK于是发送端就会快速地重传不必等待超时再重传。

这时相当于只丢了一小部分的包所以并不严重。

cwnd

时的数据都已收到该恢复过程已经结束可以回到恢复之前的状态了也即再次进入拥塞避免状态

TCP

打开就可以直观的来分析数据。

点开每一个数据包还可以看到各个协议栈各层的信息如下

抓包分析

延迟确认机制」那么第二和第三次挥手就会合并传输这样就出现了三次挥手。

三次握手异常

秒才可以发现一个「死亡」连接于是客户端连接就会断开连接。

如果客户端发送了数据包一直没有收到服务端对该数据包的确认报文则会一直重传该数据包直到重传次数超过

tcp_retries2

服务器会出现繁忙的情况当应用程序读取速度慢那么缓存空间会慢慢被占满于是为了保证发送方发送的数据不会超过缓冲区大小服务器则会调整窗口大小的值接着通过

ACK

报文通知给对方告知现在的接收窗口大小从而控制发送方发送的数据大小。

如果窗口收缩至

0发送方会定时发送窗口大小探测报文以便及时知道接收方窗口大小的变化。

超时时间会翻倍递增。

TCP

将会延迟一段时间以等待是否有响应数据可以一起发送如果在延迟等待发送

ACK

后内核会把连接从半连接队列移除然后创建新的完全的连接并将其添加到

accept

Recv-Q当前全连接队列的大小也就是当前已完成三次握手并等待服务端

accept()

Recv-Q已收到但未被应用进程读取的字节数Send-Q已发送但未收到确认的字节数

netstat

全连接队溢出的时候后续的请求就会被丢弃这样就会出现服务端请求数量上不去的现象。

当然也可以修改变成向客户端发送

RST

ACK请求就会被多次重发。

如果服务器上的进程只是短暂的繁忙造成

accept

ACK仍然会触发服务器端成功建立连接。

所以tcp_abort_on_overflow

TCP

tcp_syncookies则会丢弃若全连接队列满了且没有重传

SYNACK

2)如果「当前半连接队列」超过「理论半连接队列最大值」那么处于

SYN_RECV

半连接队列的情况下成功建立连接在前面我们源码分析也可以看到这点当开启了

syncookies

包表明确认收到了客户端的序列号同时也把自己的序列号发给对方并将自己的状态切换至

SYN_RECV这时候内核就会构建「半连接队列」来维护「未完成」的握手信息当半连接队列溢出后服务端就无法再建立新的连接。

netstat

连接因为半连接队列溢出而被丢弃。

隔几秒执行几次如果有上升的趋势说明当前存在半连接队列溢出的现象。

增大半连接队列大小不能只单纯增大

第一次握手就是正常的三次握手流程。

但如果之后再次建立连接这时客户端发送

SYN

和数据确认并将数据进一步给应用进程处理无效则会丢弃只发送正常的

SYNACK

FIN_WAIT2也就是表示主动方的发送通道就关闭了。

当被动方进入

CLOSE_WAIT

报文就直接关闭连接了不需要走四次挥手流程是一个暴力关闭连接的方式。

四次挥手由进程调用

函数意味着完全断开连接完全断开不仅指无法传输数据而且也不能发送数据。

close

函数关闭连接此时连接就会是「孤儿连接」因为它无法再发送和接收数据。

如果孤儿连接数量大于它新增的孤儿连接将不再走四次挥手而是直接发送

RST

函数关闭的孤儿连接由于无法再发送和接收数据所以这个状态不可以持续太久而

tcp_fin_timeout

是主动方四次挥手的最后一个状态也是最常遇见的状态。

当收到被动方发来的

FIN

状态存在的必要之前已经学过了可以往上翻到最前面刚学四次挥手的地方。

**主要是两点

防止历史连接中数据被后面的四元组连接错误接受保证「被动关闭连接」的一方能被正确的关闭

Linux

参数减少不同连接间数据错乱的概率。

tcp_max_tw_buckets

TIME_WAIT

参数。

但是需要注意该参数是只用于客户端建立连接的发起方因为是在调用

connect()

时起作用的而对于服务端被动连接方是没有用的。

同时还有一个前提是双方都需要打开时间戳tcp_timestamps

设置为

就会因为重复数据包的时间戳过期直接舍弃还可以防止序列号的绕回。

socket

是全双工连接就有可能出现客户端和服务端同时关闭连接两者都认为自己是主动方发送

FIN

连接是由内核维护的内核会为每个连接建立内存缓冲区内存过小就会无法充分利用网络带宽内存过大会导致服务器资源耗尽无法建立新连接。

滑动窗口

会保证每一个报文都能够抵达对方它的机制是这样报文发出去后必须接收到对方返回的确认报文

ACK

提供一种机制可以让「发送方」根据「接收方」的实际接收能力控制发送的数据量这就是滑动窗口的由来。

同时要注意发送方的窗口和接收方的窗口都是动态变化的如果不考虑拥塞控制那么两者是约等于的关系。

65535

但是因为网络的传输能力是有限的当发送方依据发送窗口发送超过网络处理能力的报文时路由器会直接丢弃这些报文。

因此缓冲区的内存并不是越大越好。

确定最大传输速度

网络是有「带宽」限制的带宽描述的是网络传输能力它与内核缓冲区的计量单位不同:

100

带宽时延积它决定网络中飞行报文的大小由于发送缓冲区大小决定了发送窗口的上限而发送窗口又决定了「已发送未确认」的飞行报文的上限。

因此发送缓冲区不能超过「带宽时延积」。

调整缓冲区大小

第一个数值是动态范围的最小值表示即使在内存压力下也可以保证的最小接收缓冲区大小4096

byte

接收缓冲区可以根据系统空闲内存的大小来调节接收窗口但是不是自动开启的需要配置

tcp_moderate_rcvbuf

同时引入了新的问题接收缓冲区调节时怎么知道当前内存是否紧张或充分呢这是通过

tcp_mem

在高并发服务器中为了兼顾网速与大量的并发连接我们应当保证缓冲区的动态调整的最大值达到带宽时延积而最小值保持默认的

不变即可。

而对于内存紧张的服务而言调低默认值是提高并发的有效手段。

型服务器那么调大

连接使用更多的系统内存这有利于提升并发能力。

需要注意的是tcp_wmem

tcp_rmem

所以接收方一定要知道发送方的消息长度不然无法解析成一个完成的用户消息。

在发送端当我们调用

函数完成数据“发送”以后数据并没有被真正从网络上发送出去只是从应用程序拷贝到了操作系统内核协议栈中。

至于什么时候真正被发送取决于发送窗口、拥塞窗口以及当前发送缓冲区的大小等条件。

TCP

最简单的方法直接规定每一个消息的长度是相通的。

但是使用很不灵活很少使用。

特殊字符作为边界

可以在两个用户消息之间插入特殊的字符接收数据时读到这个字符相当于读完了一个完整消息。

HTTP

可以自定义一个消息结构由包头和数据组成其中包头包是固定大小的而且包头里有一个字段来说明紧随其后的数据有多大。

TCP

时长后历史报文会自动消失但前提是能正常四次挥手。

例如如下的情况就能很好的解释为什么可能有历史报文

当然即使客户端和服务端的初始化序列号不一样也会存在收到历史报文的可能。

但是历史报文是否接收还要看序列号是否在接收窗口只有在窗口才会接收。

如果每次连接客户端和服务端序列号均不相同那么大概率历史报文序列号「不在」对方接收窗口从而很大程度上避免了历史报文。

初始化序列号随机化

为每个传输方向上的每个字节都赋予了一个编号以便于传输成功后确认、丢失后重传以及在接收端保证不会乱序。

序列号是一个

之后再循环回到

建立连接的时候客户端和服务端都会各自生成一个初始序列号它是基于时钟生成的一个随机数来保证每个连接都拥有不同的初始序列号。

初始化序列号可被视为一个

微秒加

也就是说序列号和初始化序列号均会发生回绕无法根据序列号来直接判断新老数据。

为了解决这个问题就需要有

TCP

另一个是能防止序列号回绕PAWS。

如果发现收到的数据包中时间戳不是递增的则表示该数据包是过期的就会直接丢弃这个数据包。

PAWS

函数会放过这个特殊的情况认为是合法的可以接收该数据包。

所以解决这个问题可以如下出发

bit

bit。

会造成兼容问题。

将与时钟频率无关的值作为时间戳时钟频率可以增加但时间戳增速不变。

这样报文太多一样会导致时间戳失去意义。

SYN

防止具有相同四元组的旧数据包被收到也就是防止历史连接中的数据被后面的连接接受否则就会导致后面的连接收到一个无效的数据保证「被动关闭连接」的一方能被正确的关闭即保证最后的

ACK

net.ipv4.tcp_tw_reuse如果开启该选项的话客户端连接发起方

在调用

函数时如果内核选择到的端口已经被相同四元组的连接占用的时候就会判断该连接是否处于

TIME_WAIT

秒那么就会重用这个连接然后就可以正常使用该端口了。

所以该选项只适用于连接发起方。

net.ipv4.tcp_tw_recycle如果开启该选项的话允许处于

TIME_WAIT

后内核会把连接从半连接队列移除然后创建新的完全的连接并将其添加到

accept

这时后续的连接就会被丢弃这样就会出现服务端请求数量上不去的现象。

半连接队列满

报文时取出该值验证如果合法就认为连接建立成功。

如果要开启只需要设置

syncookies

报文的初始化序列号其实是一个随机数会回复一个携带了正确序列号和确认号的

ACK

报文来完成关闭要注意的是必须同时满足「四元组相同」和「序列号是对方期望的」这两个条件。

killcx

ACK他的报文确认号就是服务端下一次想要接收的序列号。

用这个序列号作为

RST

等再次收到前面被网络延迟的数据包时会判断乱序队列有没有数据然后会检测乱序队列中是否有可用的数据如果能在乱序队列中找到与当前报文的序列号保持的顺序的报文就会看该报文是否有

FIN

的「序列号和时间戳」是否合法然后根据判断结果的不同做不同的处理。

SYN

变量保存。

然后会计算下一次期望收到的序列号本次例子下一次期望收到的序列号就是

301用

防止历史连接中的数据被后面相同四元组的连接错误的接收保证「被动关闭连接」的一方能被正确的关闭

TCP

keepalive也就是关闭了保活机制不会发送探测报文。

这个机制如下

TCP

保活时间的到来。

如果对端主机崩溃或对端由于其他原因导致报文不可达。

TCP

保活的探测报文发送给对端后石沉大海没有响应连续几次达到保活探测次数后TCP

会报告该

报文后续的挥手过程也都是在内核完成并不需要进程的参与所以即使服务端的进程退出了还是能与客户端完成

有数据传输

在客户端主机宕机后服务端向客户端发送的报文会得不到任何的响应在一定时长后服务端就会触发超时重传机制重传未得到响应的报文。

客户端重启就会收到这个重传报文

服务端传输给客户端无响应那么一段时间后就会触发服务端的超时重传。

如果在服务端重传报文的过程中客户端刚好把网线插回去了由于拔掉网线并不会改变客户端的

TCP

状态所以这时客户端是可以正常接收服务端发来的数据报文的然后客户端就会回

ACK

如果如果在服务端重传报文的过程中客户端一直没有将网线插回去服务端超时重传报文的次数达到一定阈值后内核就会判定出该

TCP

连接就会断开。

而等客户端插回网线后如果客户端向服务端发送了数据由于服务端已经没有与客户端相同四元祖的

TCP

机制在客户端拔掉网线后并且双方都没有进行数据传输那么客户端和服务端的

TCP

机制在客户端拔掉网线后即使双方都没有进行数据传输在持续一段时间后TCP

就会发送探测报文

保活时间的到来。

如果对端主机宕机注意不是进程崩溃进程崩溃后操作系统在回收进程资源的时候会发送

FIN

保活机制来探测对方是不是发生了主机宕机或对端由于其他原因导致报文不可达。

TCP

保活的探测报文发送给对端后石沉大海没有响应连续几次达到保活探测次数后TCP

会报告该

防止历史连接中的数据被后面相同四元组的连接错误的接收保证「被动关闭连接」的一方能被正确的关闭

针对第二个情况比如被动关闭发送

PORT」都一样的服务器发起连接了但是被使用的端口还是可以继续对另外一个服务器发起连接的。

不过即使是在这种场景下只要连接的是不同的服务器端口是可以重复使用的所以客户端还是可以向其他服务器发起连接的这是因为内核在定位一个连接的时候是通过四元组源IP、源端口、目的IP、目的端口信息来定位的并不会因为客户端的端口一样而导致连接冲突。

Linux

net.ipv4.tcp_tw_reuse如果开启该选项的话客户端连接发起方

在调用

函数时如果内核选择到的端口已经被相同四元组的连接占用的时候就会判断该连接是否处于

TIME_WAIT

秒那么就会重用这个连接然后就可以正常使用该端口了。

所以该选项只适用于连接发起方。

net.ipv4.tcp_tw_recycle如果开启该选项的话允许处于

TIME_WAIT

三次握手后才能进行。

当然也有情况是可以同时握手的需要以下两个条件同时满足

TCP

连接建立的时延。

要使用该功能客户端和服务端需要同时支持该功能。

TCP

后续通信客户端第一次握手就可以携带数据从而绕过三次握手发送数据

具体情况如下

和「数据」进行确认服务器随后将「应用数据」递送给对应的应用程序如果

Cookie

报文中的「应用数据」服务器可在握手完成之前发送「响应数据」这就减少了握手带来的

RTT

报文中发送的「应用数据」没有被确认则客户端将重新发送「应用数据」此后的

TCP

0-RTT用“pre_shared_key”和“early_data”扩展在

TCP

请求服务端收到后就返回响应至此「请求-应答」的模式就完成了随后就会释放

TCP

如果每一次都重复如上过程那就是短连接。

如果第一次请求完先不断开

Keep-Alive

Keep-Alive它必须在请求的包头中添加对应字段然后服务器收到请求同样也要添加这个响应字段。

HTTP

流水线是客户端可以先一次性发送多个请求而在发送过程中不需先等待服务器的回应可以减少整体的响应时间。

当然服务器还是按照顺序响应。

TCP

长连接的超时时间。

这就相当于给定时器计时超时就会触发回调函数释放该连接。

TCP

这个特性是不错但是它需要服务端和客户端的操作系统同时支持才能体验到而

TCP

年提出的所以市面上依然有很多老式的操作系统不支持而升级操作系统是很麻烦的事情因此

TCP

层为了保证数据的有序性只有在处理完有序的数据后滑动窗口才能往前滑动否则就停留。

HTTP/2

滑动窗口那么当发生数据丢失滑动窗口是无法往前移动的此时就会阻塞住所有的

HTTP

帧告诉对端自己可以接收的字节数这样发送方就不会发送超过这个数量的数据。

通过

BlockFrame

消耗连接Connection的全部接收缓冲。

Connection

流量控制限制连接中所有

拥塞控制算法我们熟知的慢开始、拥塞避免、快重传、快恢复策略同时也支持

CubicBytes、Reno、RenoBytes、BBR、PCC

等拥塞控制算法相当于将

是处于应用层的应用程序层面就能实现不同的拥塞控制算法不需要操作系统不需要内核支持。

这是一个飞跃因为传统的

TCP

拥塞控制必须要端到端的网络协议栈支持才能实现控制效果。

而内核和操作系统的部署成本非常高升级周期很长所以

TCP

的拥塞控制算法就可以有较快的迭代速度。

可以针对不同应用场景设置不同的拥塞控制算法。

QUIC

就可以「同时」完成建立连接与密钥协商甚至在第二次连接的时候应用数据包可以和

QUIC

密钥等就可以“无缝”地复用原连接消除重连的成本没有丝毫卡顿感达到了连接迁移的功能。

TCP

地址来寻找网络中互连的主机或路由器。

在传输层中需要通过端口进行寻址来识别同一计算机中同时通信的不同应用程序。

所以传输层的「端口号」的作用是为了区分同一个主机上不同应用程序的数据包。

传输层有两个传输协议分别是

TCP

TCP/UDP所以可以根据这个信息确定送给哪个模块TCP/UDP处理送给

TCP/UDP

模块的报文根据「端口号」确定送给哪个应用程序处理。

所以这两者共用端口并不会造成冲突过程如下

TCP

进程也会有这个报错这是因为重启的时候相当于发生了四次挥手那么主动关闭方就会处于

TIME_WAIT

连接是由四元组源IP地址源端口目的IP地址目的端口唯一确认的那么只要四元组中其中一个元素发生了变化那么就表示不同的

TCP

函数时如果选择到的端口已经被相同四元组的连接占用的时候就会判断该连接是否处于

TIME_WAIT

可以的客户端是可以自己连自己的形成连接TCP自连接也可以两个客户端同时向对方发出请求建立连接TCP同时打开这两个情况都有个共同点就是没有服务端参与也就是没有listen就能建立连接。

虽然没有

bind绑定服务器端的IP和端口所有客户端都向这个IP和端口发送和请求数据*/

bind(listen_fd,

服务器等待客户端的链接返回值cfd为客户端的socket描述符*/

cfd

实验抓包得到结果**就算不执行accept()方法三次握手照常进行并顺利建立连接。

**而且在服务端执行accept()前如果客户端发送消息给服务端服务端是能够正常回复ack确认包的。

这里就回到了之前的半连接队列和全连接队列全连接队列就是第三次握手之后会从半连接队列中取出

sock

半连接队列却不太一样因为队列里的都是不完整的连接嗷嗷等待着第三次握手的到来。

那么现在有一个第三次握手来了则需要从队列里把相应IP端口的连接取出如果半连接队列还是个链表那我们就需要依次遍历才能拿到我们想要的那个连接算法复杂度就是O(n)。

全连接队列满

如果队列满了服务端还收到客户端的第三次握手ACK默认当然会丢弃这个ACK。

会丢弃这个第三次握手ACK包并且开启定时器重传第二次握手的SYNACK如果重传超过一定限制次数还会把对应的半连接队列里的连接给删掉。

全连接队列满了之后就直接发RST给客户端效果上看就是连接断了。

RST

发来服务端不会将其放入半连接队列中而是直接生成一个cookies这个cookies会跟着第二次握手发回客户端。

客户端在发第三次握手的时候带上这个cookies服务端验证到它就是当初发出去的那个就会建立连接并放入到全连接队列中。

可以看出整个过程不再需要半连接队列的参与。

注意cookies并不会有一个专门的队列保存它是通过通信双方的IP地址端口、时间戳、MSS等信息进行实时计算的保存在TCP报头的seq里。

cookies

服务端并不会保存连接信息所以如果传输过程中数据包丢了也不会重发第二次握手的信息。

编码解码

的利用这一点如果此时攻击者构造大量的第三次握手包ACK包同时带上各种瞎编的cookies信息就会消耗很多资源。

TCP

一个数据包从聊天框里发出消息会从聊天软件所在的用户空间拷贝到内核空间的发送缓冲区send

buffer数据包就这样顺着传输层、网络层进入到数据链路层在这里数据包会经过流控qdisc再通过RingBuffer发到物理层的网卡。

数据就这样顺着网卡发到了纷繁复杂的网络世界里。

这里头数据会经过n多个路由器和交换机之间的跳转最后到达目的机器的网卡处。

此时目的机器的网卡会通知DMA将数据包信息放到RingBuffer中再触发一个硬中断给CPUCPU触发软中断让ksoftirqd去RingBuffer收包于是一个数据包就这样顺着物理层数据链路层网络层传输层最后从内核空间拷贝到用户空间里的聊天软件里。

建立连接丢包

让数据按一定的规则排个队依次处理也就是所谓的qdisc(Queueing

Disciplines排队规则)这也是我们常说的流量控制机制。

可以通过下面的ifconfig命令查看到里面涉及到的txqueuelen后面的数字1000其实就是流控队列的长度。

当发送数据过快流控队列长度txqueuelen又不够大时就容易出现丢包现象。

网卡丢包

接收数据时会将数据暂存到RingBuffer接收缓冲区中然后等着内核触发软中断慢慢收走。

如果这个缓冲区过小而这时候发送的数据又过快就有可能发生溢出此时也会产生丢包。

一个网卡里是可以有多个RingBuffer的所以上面的rx_queue_0_drops里的0代表的是第0个RingBuffer的丢包数对于多队列的网卡这个0还可以改成其他数字。

网卡性能不足

网卡作为硬件传输速度是有上限的。

当网络传输速度过大达到网卡上限时就会发生丢包。

接收缓冲区丢包

socket进行网络编程的时候内核都会分配一个发送缓冲区和一个接收缓冲区。

发送时将数据拷贝到内核发送缓冲区就完事返回了至于什么时候发数据发多少数据这个后续由内核自己做决定。

接收缓冲区作用也类似从外部网络收到的数据包就暂存在这个地方然后坐等用户空间的应用程序将数据包取走。

查看接收缓冲区

4194304不管是接收缓冲区还是发送缓冲区都能看到三个数值分别对应缓冲区的最小值默认值和最大值

min、default、max。

缓冲区会在min和max之间动态调整。

对于发送缓冲区执行send的时候如果是阻塞调用那就会等等到缓冲区有空位可以发数据。

如果是非阻塞调用就会立刻返回一个

EAGAIN

again。

让应用程序下次再重试。

这种情况下一般不会发生丢包。

当接受缓冲区满了事情就不一样了它的TCP接收窗口会变为0也就是所谓的零窗口并且会通过数据包里的win0告诉发送端不要发消息了。

一般这种情况下发送端就该停止发消息了但如果这时候确实还有数据发来就会发生丢包。

两端间网络丢包

需要知道目的地的域名。

想知道你的机器到服务器之间有没有产生丢包行为。

可以使用ping命令。

ping之后查看

mtr命令可以查看到你的机器和目的机器之间的每个节点的丢包情况。

可以看到Host那一列出现的都是链路中间每一跳的机器Loss的那一列就是指这一跳对应的丢包率。

同时因为mtr默认用的是ICMP包有些节点限制了ICMP包导致不能正常展示。

可以加一个参数使用

udp

把ICMP包和UDP包的结果拼在一起看就是比较完整的链路图了。

有个小细节Loss那一列我们在icmp的场景下关注最后一行如果是0%那不管前面loss是100%还是80%都无所谓那些都是节点限制导致的虚报。

如何解决丢包

建立了TCP连接的两端发送端在发出数据后会等待接收端回复ack包ack包的目的是为了告诉对方自己确实收到了数据但如果中间链路发生了丢包那发送端会迟迟收不到确认ack于是就会进行重传。

以此来保证每个数据包都确确实实到达了接收端。

TCP

TCP位于传输层在它的上面还有各种应用层协议比如常见的HTTP或者各类RPC协议。

TCP保证的可靠性是传输层的可靠性。

也就是说TCP只保证数据从A机器的传输层可靠地发到B机器的传输层。

这时就有可能在完成了传输层的正常传输之后应用层需要从接收缓冲区取出数据这时就可能导致丢包

解决丢包

服务器可能记录了我们最近发过什么数据假设每条消息都有个id服务器和聊天软件每次都拿最新消息的id进行对比就能知道两端消息是否一致就像对账一样。

对于发送方只要定时跟服务端的内容对账一下就知道哪条消息没发送成功直接重发就好了。

如果接收方的聊天软件崩溃了重启后跟服务器稍微通信一下就知道少了哪条数据同步上来就是了所以也不存在上面提到的丢包情况。

可以看出TCP只保证传输层的消息可靠性并不保证应用层的消息可靠性。

如果我们还想保证应用层的消息可靠性就需要应用层自己去实现逻辑做保证。

第一如果是两端通信你聊天软件里有1000个好友你就得建立1000个连接。

但如果引入服务端你只需要跟服务器建立1个连接就够了聊天软件消耗的资源越少手机就越省电。

第二就是安全问题如果还是两端通信随便一个人找你对账一下你就把聊天记录给同步过去了这并不合适吧。

如果对方别有用心信息就泄露了。

引入第三方服务端就可以很方便的做各种鉴权校验。

第三是软件版本问题。

软件装到用户手机之后软件更不更新就是由用户说了算了。

如果还是两端通信且两端的软件版本跨度太大很容易产生各种兼容性问题但引入第三端服务器就可以强制部分过低版本升级否则不能使用软件。

但对于大部分兼容性问题给服务端加兼容逻辑就好了不需要强制用户更新软件。

TCP

0这时服务端应用程序如果有数据要发送的话就发完数据后才调用关闭连接的函数如果服务端应用程序没有数据要发送的话可以直接调用关闭连接的函数这时服务端就会发一个

FIN

应答报文但是服务端应用程序可能还有数据要发送所以并不能马上发送

FIN

如果服务端应用程序有数据要发送的话就发完数据后才调用关闭连接的函数如果服务端应用程序没有数据要发送的话可以直接调用关闭连接的函数

如何关闭

不再有发送数据的能力但是还是具有接收数据的能力。

如果有多进程/多线程共享同一个

socketshutdown

函数这时如果挥手的时候客户端收到了服务端数据因为客户端无法收发数据就会直接回

RST

报文然后内核释放连接。

此时就不会经历完整四次挥手是一种粗暴的关闭。

当服务端收到

RST

后内核就会释放连接当服务端应用程序再次发起读操作或者写操作时就能感知到连接已经被释放了

RST

信号应用层代码可以捕获并处理信号如果不处理则默认情况下进程会终止异常退出。

shutdown

四次挥手过程中如果收到了服务端发送的数据客户端也是可以正常读取到该数据的然后就会经历完整的

TCP

延迟确认机制」那么第二和第三次挥手就会合并传输这样就出现了三次挥手。

TCP

延迟确认机制是默认开启的所以导致我们抓包时看见三次挥手的次数比四次挥手还多。

TCP

当有响应数据要发送时ACK

将会延迟一段时间以等待是否有响应数据可以一起发送如果在延迟等待发送

ACK

报文传给接收端主机每发送一次数据就「累加」一次该「数据字节数」的大小。

用来解决网络包乱序问题。

确认号指下一次「期望」收到的数据的序列号发送端收到接收方发来的

ACK

确认报文以后就可以认为在这个序号以前的数据都已经被正常接收。

用来解决丢包的问题。

控制位用来标识

TCP



SEO优化服务概述

作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。

百度官方合作伙伴 白帽SEO技术 数据驱动优化 效果长期稳定

SEO优化核心服务

网站技术SEO

  • 网站结构优化 - 提升网站爬虫可访问性
  • 页面速度优化 - 缩短加载时间,提高用户体验
  • 移动端适配 - 确保移动设备友好性
  • HTTPS安全协议 - 提升网站安全性与信任度
  • 结构化数据标记 - 增强搜索结果显示效果

内容优化服务

  • 关键词研究与布局 - 精准定位目标关键词
  • 高质量内容创作 - 原创、专业、有价值的内容
  • Meta标签优化 - 提升点击率和相关性
  • 内容更新策略 - 保持网站内容新鲜度
  • 多媒体内容优化 - 图片、视频SEO优化

外链建设策略

  • 高质量外链获取 - 权威网站链接建设
  • 品牌提及监控 - 追踪品牌在线曝光
  • 行业目录提交 - 提升网站基础权威
  • 社交媒体整合 - 增强内容传播力
  • 链接质量分析 - 避免低质量链接风险

SEO服务方案对比

服务项目 基础套餐 标准套餐 高级定制
关键词优化数量 10-20个核心词 30-50个核心词+长尾词 80-150个全方位覆盖
内容优化 基础页面优化 全站内容优化+每月5篇原创 个性化内容策略+每月15篇原创
技术SEO 基本技术检查 全面技术优化+移动适配 深度技术重构+性能优化
外链建设 每月5-10条 每月20-30条高质量外链 每月50+条多渠道外链
数据报告 月度基础报告 双周详细报告+分析 每周深度报告+策略调整
效果保障 3-6个月见效 2-4个月见效 1-3个月快速见效

SEO优化实施流程

我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:

1

网站诊断分析

全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。

2

关键词策略制定

基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。

3

技术优化实施

解决网站技术问题,优化网站结构,提升页面速度和移动端体验。

4

内容优化建设

创作高质量原创内容,优化现有页面,建立内容更新机制。

5

外链建设推广

获取高质量外部链接,建立品牌在线影响力,提升网站权威度。

6

数据监控调整

持续监控排名、流量和转化数据,根据效果调整优化策略。

SEO优化常见问题

SEO优化一般需要多长时间才能看到效果?
SEO是一个渐进的过程,通常需要3-6个月才能看到明显效果。具体时间取决于网站现状、竞争程度和优化强度。我们的标准套餐一般在2-4个月内开始显现效果,高级定制方案可能在1-3个月内就能看到初步成果。
你们使用白帽SEO技术还是黑帽技术?
我们始终坚持使用白帽SEO技术,遵循搜索引擎的官方指南。我们的优化策略注重长期效果和可持续性,绝不使用任何可能导致网站被惩罚的违规手段。作为百度官方合作伙伴,我们承诺提供安全、合规的SEO服务。
SEO优化后效果能持续多久?
通过我们的白帽SEO策略获得的排名和流量具有长期稳定性。一旦网站达到理想排名,只需适当的维护和更新,效果可以持续数年。我们提供优化后维护服务,确保您的网站长期保持竞争优势。
你们提供SEO优化效果保障吗?
我们提供基于数据的SEO效果承诺。根据服务套餐不同,我们承诺在约定时间内将核心关键词优化到指定排名位置,或实现约定的自然流量增长目标。所有承诺都会在服务合同中明确约定,并提供详细的KPI衡量标准。

SEO优化效果数据

基于我们服务的客户数据统计,平均优化效果如下:

+85%
自然搜索流量提升
+120%
关键词排名数量
+60%
网站转化率提升
3-6月
平均见效周期

行业案例 - 制造业

  • 优化前:日均自然流量120,核心词无排名
  • 优化6个月后:日均自然流量950,15个核心词首页排名
  • 效果提升:流量增长692%,询盘量增加320%

行业案例 - 电商

  • 优化前:月均自然订单50单,转化率1.2%
  • 优化4个月后:月均自然订单210单,转化率2.8%
  • 效果提升:订单增长320%,转化率提升133%

行业案例 - 教育

  • 优化前:月均咨询量35个,主要依赖付费广告
  • 优化5个月后:月均咨询量180个,自然流量占比65%
  • 效果提升:咨询量增长414%,营销成本降低57%

为什么选择我们的SEO服务

专业团队

  • 10年以上SEO经验专家带队
  • 百度、Google认证工程师
  • 内容创作、技术开发、数据分析多领域团队
  • 持续培训保持技术领先

数据驱动

  • 自主研发SEO分析工具
  • 实时排名监控系统
  • 竞争对手深度分析
  • 效果可视化报告

透明合作

  • 清晰的服务内容和价格
  • 定期进展汇报和沟通
  • 效果数据实时可查
  • 灵活的合同条款

我们的SEO服务理念

我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。

提交需求或反馈

Demand feedback