最后更新:2022-05-19 00:30:02 手机定位技术交流文章

握手建立连接流程
这份行动图代表了我们经常利用的编码进程,把我们的客户和服务连接起来。
这与下面的简化服务端伪编码相对应。
int main()
{
*第1步 : 构建倾听器_fd 服务器终端 监听套接字描述器* /
listen_fd = socket(AF_INET, SOCK_STREAM, 0);
*第2步 绑定服务器的地址和端口所有客户发送和接收数据到该 IP 地址和端口* / 。
bind(listen_fd, xxx);
*第3步:开始在服务器上收听*/
listen(listen_fd, 128);
*第4步:服务器等待客户的连接。返回被描述为客户端套接字说明*/
cfd = accept(listen_fd, xxx);
*第5步:阅读客户数据*/
n = read(cfd, buf, sizeof(buf));
}
我猜你也熟悉这个假代码
应该提到的是执行。listen()以后还会有的accept()方法。
当服务器启动时, 最后一个应用程序通常被屏蔽 。accept()里。
顾客已经准备好了
考虑简化的客户伪编码。
int main()
{
*第1步:创建客户套接字描述符,缩写为参考*/
cfd = socket(AF_INET, SOCK_STREAM, 0);
*第2步:连接方法,开始IP与端口号* 之间的服务器端连接。
ret = connect(cfd, xxxx);
*第4步:将数据发送到服务器端* /
write(cfd, buf, strlen(buf));
}
客户不那么复杂,要做到这一点。socket之后,直接就发起connect方法。
返回服务端时,发现迄今为止一直被阻塞的接受方法,结果被退回。
两者之间可能存在有效的联系,使我们能够愉快地阅读和写作。
因此,今天的问题是,如果没有这种可接受的方法,能否形成TCP联系?
其实只要在执行accept()之前执行一个sleep(20),然后立即采用与客户有关的方法,然后用一个包包来作出结论。

未执行接受捕获结果
根据包包的结果进行了三次握手练习,并成功地建立了连接,尽管没有采用接受()方法。
更糟糕的是,在实施服务端的接受()之前,如果客户向服务提供者传递信息,服务将能够对一揽子方案作出适当答复。
并且,sleep(20)当它完成后,服务器做对了。accept()——向客户传达的信息可以定期收到。
我们可以更多地了解为什么通过这种现象。我想了解以下三种握手的具体细节。
我们从采访剩下的八张纸开始 握手三次

TCP三次握手
服务端代码,即套接字捆绑方法,可以连接到监听端口,然后运行。listen方法后,就会进入监听(LISTEN内核将适合他们每个人LISTEN状态的socket分布两种类型的队列:半连接队列和完整连接队列。

每个听众索克特都有 完整和半完整的连接队列
半连接队列和完整连接队列有什么区别?

完整连接队列和半连接队列
服务器首次在半连接的队列( SYN 队列) 中握手, 并将sock队 队 队 队 队 队 队 队 队 队 队 队 队sock都处于SYN_RECV状态。
完整连接队列(ACCEPT 队列),服务结束后的半连接队列获得第三次握手sock删除它们并将其置于完整连接队列中。sock都处于ESTABLISHED内部的连接正等待服务提供商运行接受()并删除它。
大家可以看到,论文开头提出的问题已经解决,没有必要建立联系。accept()要从完整连接队列中拉动连接, 请使用接受 () 即可 。
让我们回到这两条线上来。
它被称为队列, 但其实是一个链桌(icsk_ accupt_queue) 和一个半线( syn_table) 表格 。

半连接全连接队列的内部组织
为何必须建立半连接线作为散列表?
我们必须比对所有连接 与队列。他本质是个链表,因为也是线性结构,假设它是一个排队 没有问题。它拥有已经建立的所有关系。这些连接已准备好断开 。连线被服务供应商接受两者之间的关联是没有区别的。只要是个连接就行,所以只需从队列中选择它 。程序算法很复杂O(1)。
另一方面,半连接队列是不一样的。因为队列中的所有链接都断了我还在等第三次握手所以现在有第三次握手了如果您想要参与此程序, 您必须从队列中抓取连接, 然后从 IP 端口获取连接 。如果半连接队列继续是一个链桌结果是,我们不得不来回走来走去。因此,我们可以取得所希望的联系。算法的复杂性是 O(n) 。
此外,如果半连接队列建成桥表,则探测半连接返回的方法复杂性。O(1)了。
因此,全连通队列是作为提高效率的连锁桌建成的,而半连通队列则是作为Hashi手表创建的。
你觉得这两个队有多大?
查看全连接队列
# ss -lnt
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 127.0.0.1:46269 *:*
通过ss -lnt命令,您可以查看连接队列的总大小。Send-Q它指的是连接队列的最大值。 您可以在我上面看到最有价值的东西是..128;Recv-Q这是完整连接队列的当前使用值。 这是我在这里使用的 。0第一,整个连接线是空的,连接线是断开的。
当上面Send-Q和Recv-Q当值接近时, 整个连接队列可能已经满。 使用以下命令来检查队列溢出 。
# netstat -s | grep overflowed
4343 times the listen queue of a socket overflowed
上面说明发生过4343次全部连接队列溢出。 这是过去发生的次数 。
如果配合使用watch -d命令,可以自动每2s同一顺序定期进行,突出变化的数值部分,如果溢出量上升,则表明溢出量正在发生。
# watch -d 'netstat -s | grep overflowed'
Every 2.0s: netstat -s | grep overflowed Fri Sep 17 09:00:45 2021
4343 times the listen queue of a socket overflowed
查看半连接队列
没有命令直接看到半连接队列中, 但是因为它在半连接队列中, 它就在那里。SYN_RECV,通过计算此状态的连接次数,间接获得半连接队列的长度。
# netstat -nt | grep -i '127.0.0.1:8080' | grep -i 'SYN_RECV' | wc -l
0
注意完整连接队列和半连接队列都是挂在某个Listen socket上的,我这里用的是127.0.0.1:8080您可以将其更改为您想要查看的 IP 端口 。
如你所见 我的半连接队列是..0这很典型,谁会留在半连接线上?
当队列中的半连接数增加时,它们最终会溢出,并可能从下面的命令中看到。
# netstat -s | grep -i "SYNs to LISTEN sockets dropped"
26395 SYNs to LISTEN sockets dropped
正如你所见,一切都在我的机器上发生26395连接队列的第二部分也满溢。watch -d命令使用。
# watch -d 'netstat -s | grep -i "SYNs to LISTEN sockets dropped"'
Every 2.0s: netstat -s | grep -i "SYNs to LISTEN sockets dropped" Fri Sep 17 08:36:38 2021
26395 SYNs to LISTEN sockets dropped
当整个队列被填满后会怎么样?
如果队列已满, 客户端将另外获得第三次 ACK 握手, 默认情况下会忽略 。
然而,除弃儿外,还有别的事要做,那将是很痛苦的。tcp_abort_on_overflow参数的影响。
# cat /proc/sys/net/ipv4/tcp_abort_on_overflow
0
tcp_abort_on_overflow当完整行填满时, 第三个握手的ACK包被丢弃, 定时器被激活, 第二个握手的 SYN+ACK 被再次传送, 相关半连接队列中的连接如果重复过多次则被删除 。

tcp_ abandon_on_ overfly 0 上横飞 0
tcp_abort_on_overflow当连接队列完整时, 设置 1 将立即将 RST 传送给客户端。 因此, 链接被切断 。
当服务端口没有被窃听, 客户端试图连接, 服务提供方发送 RST 。 在这两种情况下, 情况都一样, 因此当客户当前收到 RST 时, 很难判断该端口是否被窃听, 或者整个连接队列是否满载 。

tcp_ abandon_on_overfly 1, tcp_ abandon_ abandon_on_ overfly 1, tcp_ abandon_ off_ overfly 1, tcp_ abandon_ off_ overfly 1
如果半连接线完全满了怎么办?
经常被开除,但并非不可能tcp_syncookies控制参数至关重要,但了解为什么连接线的后半部分被填充是更重要的临界参数,但了解为什么连接线的后半部分被填充是更重要的。
首先我们需要明白,一般情况下,"生存"这个词其实很简短第一次和第三次握手是可以接受的如果半连接都满了,最初的握手请求旨在证明服务所有人经常被要求握手。如果这是一个在线游戏应用程序,有很多请求要来这说明你可能发财了然而,现实却更愚蠢。你可能遭遇过SYN洪水袭击
称为SYN洪水的袭击可以简单理解为,袭击者提出一个疯狂的客户 最初的握手请求在服务提供商对第二次握手作出答复后,第三次握手 客户还活着这样做,我们可以填补服务中的半线。因此,典型的连接并不正常。

syn攻击
这个案子怎么办 能避免半连接队列吗
有,上面提到的tcp_syncookies派上用场了。
# cat /proc/sys/net/ipv4/tcp_syncookies
1
当设定为 1 时, 当客户端第一次摇动 SYN 的手时, 服务器不会将其放在半连接队列中, 而是直接生成一个 。cookies,这个cookies我会再握手,然后还给委托人 委托人在第三次握手时带着这个cookies服务端确认是它发送的, 然后构建连接并将其放在完整连接队列中。 可以看到, 在整个过程中不再需要半连接队列 。

tcp_syncookies=1
饼干会积压吗?
生成是cookies它的位置是哪里?
如果有的话,我们可以考虑另一种选择。cookies这就像半连接队列 最后会充满SYN洪水袭击
实际上cookies将不保存特定的队列,而是使用双方通信方IP地址端口、时间邮票、MSS等实时计算,并在TCP主页上保存。seq里。

tcp 信头_ seq 位置
在客户第三次握手后,通过后续程序建立了连接,以恢复对话两端的IP地址、端口、时间戳和MSS。
为什么饼干不接手半连接队列呢?
目前看下来syn cookies策略保存了半链接行所需的队列内存, 同时解决了 SYN Flood 袭击 。 为什么不删除半链接线?
凡事皆有利弊,cookies虽然软件对SYN洪水袭击有效,但有一定的缺陷。 因为服务终端无法保存连接信息,如果数据包在传输过程中丢失,第二个握手信息将不再重新发布。
另外,编码解码cookies它们比CPU更昂贵, 所以如果攻击者在第三手提包(背包)上 储存了各种闪闪发光的物品。cookies信息,服务端收到ACK包然后,他们以为自己是认真的饼干,然后去解码(消费CPU),只是发现自己在被扔之前没有被妥善包裹好。
这种通过构造大量ACK包由于CPU资源耗竭,试图消耗服务方资源,即所谓的 " ACK攻击 ",可能导致对一项积极要求不作答复。

ack攻击
如果人们不听话,如何建立关系?
那既然没有accept这难道不是建立联系的手段吗?listen方法,也能建立连接?是的,如前一篇文章所述,客户可以与自己联系(TCP)。两个客户也可以同时请求连接(同时打开TCP) 。两种情况都有一个共同点。只是没有服务供应商参与我不知道该说什么 因为我不知道我在说什么就能建立连接。
当时文章最后也留了个疑问,如果人们不听话,如何建立关系??
我们知道执行listen方法时,会创建完整连接队列和半连接队列。
在整个三次握手中,连接信息保存在两个队列中。
因此,如果您有一个握手位置, 可以根据IP 端口等信息获取插座信息, 它将连接在一起 。
客户有半连接队列吗?
显然没有,因为客户没有执行。listen,因为完整连接队列和半连接队列都是在执行listen内核是使用这种方法自动生成的。
另一方面,内核包括一个可用于储存的全球散列表。sock无法打开消息。 这是整个图片 。hash表其实还细分为听着哈哈等待,但因为细节太多,就足够理解的是,有完全的散沙图像。
客户使用 TCP 自我连接连接连接 。connect方法时,最后,他们将其连接数据输入了这个全球散列表。然后将信息发出,当信息通过环状地址 返回到TCP传输层时我不确定我是否有信心 我还能再做一次再次从这个全球混凝土获取信息 。所以我给我的手提包 一点点摇晃。最后成功建立连接。
同时,TCP也开放,但客户人数已从1人增加到2人。
每一个socket执行listen时,内核都会自动创建一个完整连接队列和半连接队列。
在第三次握手之前,TCP连接将放在半连接队列中,直到第三次握手到来。
accept方法它实际上与三次握手毫无关系,只是为了从整个连接线中取出一条链接。
出于性能原因,半连接队列原计划作为桥表,但整个连接队列实际上是一个链表。
排成一排 第三次握手会被丢弃tcp_abort_on_overflow=1,还会直接发RST给客户端。
半连接线已经填满了 也许是因为他们有SYN Flood攻击,可以设置tcp_syncookies,绕开半连接队列。
客户端没有完整连接队列和半连接队列,但有一个全局hash,可以通过它实现自连接或TCP同时打开。
本文由 在线网速测试 整理编辑,转载请注明出处。