新闻详情

新闻详情

首页 / 资讯中心 / 详情

TCP三次握手与四次挥手全解:从原理到Python socket实践

发布时间:2026/10/1 3:31:58来源:尧图网络
TCP三次握手与四次挥手全解:从原理到Python socket实践
1. 面试题拆解这道题到底在考什么如果只看题目字面很多人会觉得这就是一道背诵题把三次握手和四次挥手的流程背下来然后回答为什么是三次、为什么是四次完事。但如果你真在面试场上这么答大概率会被追问到哑火。这道题在 Python 后端、网络运维、爬虫开发等岗位的面试里出现频率极高但它真正考察的从来不是“背流程”。它考察的是你对 TCP 状态机、报文段语义、全双工通信特性的理解深度。面试官让你用 Python 写过 socket 通信但更想知道的是——当你调用socket.connect()时内核里到底发生了什么当你调用socket.close()时为什么对端不会立刻收到 FIN。我在带团队面试时通常会把这道题拆成三个层次来看第一层能不能准确画出两次握手的报文交互图说清楚 SYN、ACK、FIN 的标志位和序列号含义。第二层能不能说出“为什么不能是两次”和“为什么挥手必须是四次”的底层逻辑而不是背诵“防止已失效的连接请求报文段突然传到服务端”这类标准答案。第三层能不能结合代码和实际网络现象来解释比如 TIME_WAIT 状态过多会导致什么后果Python 写服务器时为什么会出现Address already in use。这篇文章会按照这个思路展开把三次握手和四次挥手讲透顺便把 Python 环境下我踩过的一些坑也说清楚。不管你是准备面试还是工作中排查网络问题这篇都值得从头到尾过一遍。2. 三次握手全流程拆解从 SYN 到确认2.1 握手过程的报文交互与状态迁移先说流程本身。三次握手指的是建立一个 TCP 连接时通信双方需要交换三个报文段以确认彼此的收发能力都正常。假设客户端是 A服务端是 B第一步A 主动向 B 发送一个 SYN 报文段表示“我想跟你建立连接”。这个报文段里带上了 A 的初始序列号我们记作seq x。此时 A 进入SYN_SENT状态。第二步B 收到 SYN 报文后如果同意建立连接就会回复一个报文段同时把 SYN 和 ACK 两个标志位都置为 1。这个报文段里B 的初始序列号记为seq y确认号则是ack x 1含义是“我收到了你的 SYN下一次你发的数据我要从 x1 开始往后数”。此时 B 进入SYN_RCVD状态。第三步A 收到 B 的 SYNACK 后再回复一个 ACK 报文段确认号为ack y 1。这个报文发出后A 进入ESTABLISHED状态。B 收到这个 ACK 后也进入ESTABLISHED状态。连接建立完成。用 Python 的socket模块来对照一下这段过程几乎是透明的import socket # 服务端 server socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind((0.0.0.0, 8080)) server.listen(5) # 客户端 client socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect((127.0.0.1, 8080))那行client.connect()一执行内核就帮你走完了上面三个报文段的交互。你不需要手动构造 SYN但要知道它确实在这个调用里发生了。这也是为什么很多人背了流程、却连connect()阻塞了多久都不知道——它阻塞的时间就是三次握手完成所需的一个 RTT往返时延左右。2.2 序列号与确认号的响应关系是理解握手的关键很多教程画了三段箭头但没解释清楚为什么 ACK 的确认号必须是对方的初始序列号加 1。这里的关键在于SYN 报文段本身会消耗一个序列号。虽然它不携带应用层数据但它是一个需要被确认的控制报文所以当接收方收到 SYN 时它期待的下一个字节序号就是对方的初始序列号 x 1。同样第三次握手中的 ACK 报文段本身不消耗序列号它只是纯确认。所以严格来说在建立连接的过程中双方真正“消费”的序列号只有 SYN 这一位。顺着这个思路你就能理解为什么三次握手结束之后双方各自都知道“我发的数据对方能收到我收数据的能力对方也认可”。用最通俗的话说第一次握手A 告诉 B我有发送能力你确认一下你的接收能力。第二次握手B 告诉 A我收到了你的消息我的发送能力你也验证一下。第三次握手A 告诉 B我已经收到你的回应两边收发都通畅。前两次握手只能让 A 确认“B 能收、能发”但这个时候 B 并不知道“A 能不能收到我的消息”。只有第三次握手到达 B 之后B 才能确认 A 的接收能力正常。这个逻辑缺口就是必须存在第三次握手的直接原因之一。3. 为什么必须三次握手两次握手会导致什么后果3.1 解决“已失效的连接请求”引发的错乱教科书上最经典的答案是为了防止已经失效的连接请求报文段突然又传到服务端导致服务端白白建立一条无效连接浪费资源。我结合一个具体场景来说明这个问题的严重性。假设 A 发出一个 SYN 请求结果这个报文在网络里堵了很久A 迟迟没收到确认超时后 A 重发了一个 SYN。最终重发的 SYN 正常完成了握手A 和 B 建立了连接传完数据后正常关闭。这时候那个最早发出的、堵在网络里的 SYN 报文段如果终于到达了 B 会怎样在没有第三次握手的情况下B 会认为这是一个新的连接请求于是回复 SYNACK然后进入ESTABLISHED状态为一条压根不存在的连接分配缓存和资源。A 收到这个 SYNACK 后会非常困惑因为它从来就没发起过这条连接。B 这边资源被白白占用等超时才能释放。有了第三次握手情况就完全不同了B 发出的 SYNACK 如果得不到 A 的 ACK 回应这条半开连接会在超时后被系统回收不会进入已建立状态。A 也不会被无效报文干扰。3.2 防止资源浪费只是表象本质是单向确认无法覆盖双向能力如果你只是记“防失效连接”面试官再追问一句“两次握手不也能确认双向通道吗”你就容易卡壳。因为从报文交互上看两次握手其实是能完成“双向摸索”的——A 发 SYNB 回 SYNACKA 收到后不也能确认两边都通实际上这恰恰是最容易混淆的点。我们需要区分“通道双向可用”和“双方各自确认对端能力”这两件事。两次握手时A 收到了 B 的 SYNACK确实能确定两边都能收发但 B 缺一个来自 A 的、针对自己报文的明确确认。在 B 的视角里它发出 SYNACK 之后无法确认 A 是否真的收到了自己的初始序列号。如果 A 没收到那 B 的seq y对 A 来说就是一个未知数后续通信中 A 就无法正确解析 B 的报文。打个比方你跟合作方第一次对接你发了邮件说“我是 A我的编号是 x”对方回复“我是 B我的编号是 y我收到了你”。如果你不再回复对方就不知道你收到没有——你对他的编号一无所知。第三次回复就是告诉对方“你的编号我记下了咱们正式开始”。这个闭环对应的是 TCP 序列号同步的完整性。3.3 三次握手 vs 两次握手实际工程的取舍当然理论上也存在“两次或更少的握手就能建立可靠连接”的协议设计比如某些专用协议会直接用单报文握手。但 TCP 面向的是广域网、可能乱序、可能丢包、可能重复的网络环境必须考虑最坏情况。三次握手是在“开销可接受”和“确保最低限度可靠”之间找到的平衡点。从数据上看两次握手把建立一条新连接时可能出现的安全隐患转移到了数据传输阶段——你不得不额外引入检测机制来判断这条连接是否真的建立成功而三次握手虽然多了一个 RTT 的建立时延却把确认工作前置了。对于绝大多数应用场景来说多等一个 RTT 换来的确定性明显更划算。提示面试时如果被问到“为什么不是四次”可以这样说——三次已经保证了双方收发能力和序列号同步第四次属于纯冗余确认只会增加时延和额外资源消耗没有任何收益。4. 四次挥手详解从 FIN 到 TIME_WAIT4.1 挥手过程与状态流转的完整梳理连接建立之后通信双方的地位是对等的都可以主动发起关闭。四次挥手以最常见的“客户端主动关闭”为例来说明流程如下第一次挥手客户端发出一个 FIN 报文段序列号记为seq u表示“我的数据发完了我不再向你发送应用层数据了”。客户端进入FIN_WAIT_1状态。第二次挥手服务端收到 FIN 后回复一个 ACK 报文段确认号ack u 1表示“我收到了你要关闭的通知”。服务端进入CLOSE_WAIT状态。客户端收到这个 ACK 后进入FIN_WAIT_2状态。这里有一个特别容易忽略的点服务端收到 FIN 后不需要立刻也发 FIN。因为 TCP 是全双工的客户端关闭了它的发送方向但服务端正向客户端发送数据这个方向还是通的。服务端可能还有数据没发完所以先只回一个 ACK继续把剩余数据传完。这正是“能关闭一个方向、另一个方向还能继续传”的半关闭状态。第三次挥手服务端的数据全部发完后发送 FIN 报文段序列号记为seq w表示“我的数据也发完了现在可以关闭了”。服务端进入LAST_ACK状态。第四次挥手客户端收到服务端的 FIN 后回复 ACK确认号ack w 1然后客户端进入TIME_WAIT状态。服务端收到这个 ACK 后进入CLOSED状态。需要注意的是服务端在收到第四次挥手的 ACK 后就可以直接关闭了但客户端并不会立刻进入CLOSED而是要在TIME_WAIT状态停留 2MSL最长报文段寿命的两倍时间。这是四次挥手中面试官最爱追问的一个细节。4.2 用 Python 观察半关闭状态先给一段能在 Python 里直观感受半关闭特性的代码。服务端负责接收客户端传来的文件收完就关闭接收方向但仍可以继续发状态消息给客户端import socket import time def file_server(addr: str, port: int): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((addr, port)) s.listen(5) conn, client_addr s.accept() with conn: # 先收客户端数据 with open(received.bin, wb) as f: while True: data conn.recv(65536) if not data: break f.write(data) # 数据收完但还可以往客户端发通知 conn.sendall(bfile received, shutting down write side) time.sleep(1)对应地客户端可以调用shutdown(SHUT_WR)来表示“我的发送方向关闭了但我还能持续接收服务端后续的数据”这就是socket.shutdown()与socket.close()在语义上的关键区别import socket with socket.create_connection((127.0.0.1, 8080)) as c: c.sendall(bimportant payload) c.shutdown(socket.SHUT_WR) # 告知服务端客户端不再发送数据 remaining c.recv(65536) print(remaining.decode())close()会立刻释放整个 socket 的所有方向而shutdown(SHUT_WR)只关闭发送方向接收方向仍然有效。很多 Python 初学又在写网络服务的人遇到“为什么我调了close()之后对端还收得到数据”这类问题时根源就在这里——他们把“关闭连接”和“关闭发送方向”混为一谈了。4.3 挥手中的状态机转换速查这块内容适合用一张表直接记住实际排查时靠它快速定位问题状态名所属端触发条件后续走向FIN_WAIT_1主动关闭方发出 FIN 后收到对端 ACK 后进入 FIN_WAIT_2FIN_WAIT_2主动关闭方收到 ACK 后收到对端 FIN 后发起最终 ACKCLOSE_WAIT被动关闭方收到 FIN 后应用层调用 close() 后发出 FINLAST_ACK被动关闭方发出 FIN 后收到对端 ACK 后进入 CLOSEDTIME_WAIT主动关闭方发出最终 ACK 后等待 2MSL 后进入 CLOSED这张表在排查连接泄漏和 socket 状态异常时特别有用。比如你用netstat看到一堆CLOSE_WAIT说明服务端应用层没有正确关闭 socket看到一堆TIME_WAIT说明主动关闭方在频繁建立和断开短连接。5. 为什么挥手必须四次全双工的本质要求5.1 两次挥手为什么行不通要理解为什么挥手必须是四次就要回到 TCP 的根本特性全双工。一条 TCP 连接实际上是两个独立的单工通道组合而成A 到 B 一个方向B 到 A 另一个方向。这两个通道的关闭在时间上不一定同步——A 说“我不发了”并不代表 B 也立刻没话说了。如果参考三次握手改成三次挥手最极端的情况是这样的客户端发 FIN服务端把 ACK 和 FIN 合并到一个报文里回给客户端。那要求是什么要求服务端在收到 FIN 的同时也已经没有数据要发了。但服务端很可能还需要一点时间处理收尾工作——比如把缓冲区里剩余的数据刷到磁盘或者给客户端返回最终的处理结果。它不能保证 ACK 和 FIN 能同时发出。所以 TCP 的设计者把 ACK 和 FIN 拆开了先回 ACK 表示“我收到了你的关闭请求”等到应用层也确实准备好关闭了再发 FIN。这中间隔了多少时间完全取决于服务端应用代码的执行速度。5.2 延迟的 FIN 不是缺陷而是设计妥协从实时性上看第二和第三次挥手之间有一个“等待窗口”可以把这段时间理解为“被动关闭方在收拾东西”。这个等待可能很短也可能很长极端情况下应用层一直不调用close()服务端就会一直停在CLOSE_WAIT状态连接永远无法彻底关闭。我在线上排查过一个 Python 服务的问题客户端频繁断开连接服务端进程的句柄数不断增长最后Too many open files。用ss -tanp一看大量连接停留在CLOSE_WAIT状态。原因就是服务端在读取客户端数据时发生了异常异常分支里没有调用close()关闭 socket导致 TCP 协议栈收到了客户端的 FIN但应用层始终不发出 FIN。这也是幕后逻辑最值得反复强调的一点协议栈只负责在应用层调用close()之后发出 FIN它不会替你的应用层决定何时才算“数据收发完毕”。5.3 客户端收到服务端 FIN 之后为什么不立即关闭第四个挥手之后主动关闭方会进入TIME_WAIT而被动关闭方直接进入CLOSED很多人觉得这一步不对称、很浪费。为什么客户端不跟服务端一样直接关闭两个核心原因第一要确保最后一个 ACK 能送达服务端。这个 ACK 报文本身也可能在网络中丢失。如果客户端直接进入CLOSED服务端在LAST_ACK状态下一直收不到 ACK会不断重发 FIN客户端又没有进程在监听这个连接了服务端就会陷入无限重传的尴尬。TIME_WAIT存在的意义就是给客户端留出时间窗口来回应可能是重发的 FIN。第二要防止旧连接的报文段“乱入”到新连接中。同一个四元组源 IP、源端口、目的 IP、目的端口在网络里可能很快被复用。如果没有TIME_WAIT的等待期前一个连接中还在网络里游荡的迟到报文就有可能被新连接当作有效数据解析造成数据污染。等待 2MSL 基本可以保证一个报文在网络中的最长生存时间都过去了不会再出现串线问题。关于TIME_WAIT等待时长RFC 793 的建议是 2MSL但 MSL 在不同操作系统里取值不同。Linux 下常见设置为 30 秒到 60 秒也就是说TIME_WAIT通常持续 60 到 120 秒不是大家想象的几十毫秒。这也是高并发短连接场景下你会看到大量TIME_WAIT堆积的原因。6. 用 Python 模拟和验证握手的几个实操方法6.1 通过系统命令观察握手状态残留在你自己电脑上最容易复现的实验是用 Python 起一个最简单的 socket 服务端然后用客户端连接一次后立刻断开紧接着用ss或netstat查看端口状态。# 终端1启动服务端 python3 -m http.server 8900 # 终端2客户端主动连接后关门 python3 -c import socket, time; ssocket.socket(); s.connect((127.0.0.1, 8900)); s.close(); time.sleep(0.5) # 终端3立刻查看状态 ss -tan | grep 8900在主动关闭方也就是那个执行close()的 Python 客户端上你会看到端口处于TIME_WAIT。如果从服务端那一侧去看通常只看到LISTEN和ESTABLISHED瞬时状态因为它不是主动关闭方。这个实验帮助你理解TIME_WAIT永远只出现在主动关闭方一侧。还有一个非常值得做的实验是验证“半关闭”能不能真的在应用层体现出来。刚才 4.2 节给的代码里客户端用shutdown(SHUT_WR)之后服务端读到的recv()会返回空字节此时服务端知道对端不再发送但服务端仍然可以回数据给客户端。你可以把服务端开成两个线程一个负责recv一个负责send中间随意延迟几秒客户端会稳定收到延迟后的数据。6.2 常见案例Address already in use 怎么和四次挥手关联Python 写 TCP 服务端时经常会遇到这样一个报错# OSError: [Errno 98] Address already in use如果服务端程序崩溃重启监听同一个端口时报这个错很多人第一个想到的是改端口。实际上这很可能跟TIME_WAIT有关前一个服务进程作为主动关闭方它的 socket 还停留在TIME_WAIT状态此时这个四元组还没被内核释放你不能立刻绑到相同的地址和端口上。解决办法有两种。一种是在 bind 之前设置SO_REUSEADDRs.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)另一种是干脆把服务端设计成永远不做主动关闭方——服务端通常在客户端断开后才收到 FIN它处于被动关闭方根本不会进入TIME_WAIT。但如果服务端主动断开比如主动关闭一条空闲连接那它就是主动关闭方会留下大量TIME_WAIT连接。高并发服务里这些TIME_WAIT连接本身并不消耗大量内存但会占用端口和连接表项数量超过上限就会影响新连接建立。面试的时候如果能主动把这个报错和TIME_WAIT、SO_REUSEADDR串起来讲绝对比只背流程图要加分。因为这说明你真的写过高并发网络服务而不是只看过教程。6.3 tcpdump 抓包亲眼看一次握手如果你手边有 Linux 环境我强烈建议做一次抓包验证。整个过程会非常直观地让你把“书上画的三个箭头”和“网上传输的真实报文”对应起来。# 终端1抓包 sudo tcpdump -i lo port 8900 -S -XX # 终端2跑一个简单交互 python3 -c import socket, time; ssocket.socket(); s.connect((127.0.0.1, 8900)); s.send(bping); time.sleep(1); s.close()注意-S参数是让 tcpdump 打印绝对序列号否则你会看到相对序列号对理解三次握手的序列号变化没有帮助。在抓包结果里你能清晰看到Flags [S]的 SYN 报文seqxxx这是客户端发出的。Flags [S.]的 SYNACK 报文seqyyyackxxx1这是服务端回应的。Flags [.]的纯 ACK 报文ackyyy1这是客户端确认的。再往下看能看到Flags [F.]、Flags [.]、Flags [F.]、Flags [.]四段报文对应四次挥手。你把这组抓包结果和本文前面的流程描述对着看一遍比死记硬背十遍都有效。7. 面试答题思路与追问应对7.1 推荐答题结构分层递进式面试官问出这道题之后你的回答不要一次性把所有细节倒出来而是要有节奏地推进。我建议按下面的结构来第一层先给全景三次握手是建立连接时的报文交换流程四次挥手是释放连接时的报文交换流程两者都是为了保证 TCP 的可靠通信。第二层把每一次报文交互讲清楚带标志位和序列号变化。这里不要绕开细节面试官能通过你的描述判断你是真懂还是背下来的。第三层重点回答“为什么”。三次握手的原因从可靠性和防失效连接两个角度分别展开四次挥手的原因从全双工特性切入说明 ACK 和 FIN 的分裂是必然的。第四层如果时间允许把TIME_WAIT和实际生产问题带一句。不是所有面试都需要答到这一层但听到面试官追问TIME_WAIT相关话题时你要能顺滑地接上。7.2 Python 相关的追问方向既然题目和 Python 挂钩面试官大概率会从语言角度追问。我整理了几个出现频率很高的问题每一个都附上我的回答思路问题一socket.connect()对应三次握手的哪一步整个connect()调用对应三次握手的全部过程它发起 SYN然后阻塞等待 SYNACK再发送 ACK。正常返回时连接处于ESTABLISHED。问题二为什么服务端 accept() 返回的连接已经完成握手accept()是从内核的已完成连接队列里取出一条连接它的三次握手已经完成后才会进入这个队列所以accept()本身不参与握手过程。这就解答了一个常见的困惑accept()为什么不是同步等待握手的那一步。问题三客户端调 close() 后为什么服务端读不到数据了close()把发送和接收两个方向都关闭了等价于同时执行半关闭的两个方向。服务端的recv()收到 EOF返回空字节。这里可以引到shutdown()上说明半关闭的语义。问题四用 asyncio 写的服务器连接关闭时怎么控制四次挥手的时机asyncio的writer.close()只是立即关闭传输层底层 socket 是否调用close()取决于事件循环的清理逻辑。通常await writer.wait_closed()会等待传输层关闭完成。这个问题更多的落脚点其实还是对半关闭和连接状态的理解。7.3 常见误区与用自己的话讲清楚的能力我在面试里经常看到的错误是把“三次握手”画成客户端一次、服务端一次、客户端一次但说不清每一次的报文里的确认号是怎么算出来的还有人说“第二次握手时服务端同时把 ACK 和 SYN 合并成一个报文”这是因为两次报文同时到达造成误解。合并发生在第二个报文且这是必然行为前提是服务端同意连接且这个报文正好能携带自己要发的初始序列号。另外有一个高频错误是“四次挥手时客户端先发 FIN服务端回 FIN 后客户端回 ACK。” 少了一次服务端先回 ACK 的步骤。漏掉这一节就完全无法解释为什么挥手多了一次。面试官听到这种残缺回答时基本能立刻判断出你是背的不是理解的。经历过几次面试后你会发现检验自己有没有真正理解一个东西的最好办法就是能不能完全不用“背”的惯性把每一步都用生活化的语言重新讲一遍。TCP 三次握手就好比第一次见面互相介绍并交换微信你确认我、我确认你、我再确认一次你记住了我四次挥手就好比挂电话我说“我要挂了”你说“收到我话还没说完”等你把话都说完了再跟我说“我说完了”我最后回一句“好我知道了”然后过一会儿才真正挂断。这套类比虽然不严谨但能帮人搭起理解的骨架在这个骨架之上再填报文细节记忆牢固得多。8. 我踩过的坑、以及一些可能对你有用的建议8.1 高并发短连接场景下的 TIME_WAIT 处理我之前维护过一个 Python 写的 HTTP API 服务压测时发现连接数一旦上去服务吞吐量就剧烈抖动。ss -tan一看客户端那一侧堆积了几万个TIME_WAIT连接。原因很明确PHP 风格的“每次请求新建连接、用完立刻关闭”的用法在高 QPS 下会产生巨量主动关闭方。解决办法思路不是调低 TIME_WAIT 时间更不要在代码里尝试跳过这个状态。最常规的优化方向是长连接复用比如 HTTP 的 keep-alive让一条 TCP 连接承载多个请求。如果你只能用短连接就要确认客户端是否设置了SO_LINGER或 TCP 快速回收之类影响正常断开的参数——这些参数不合理设置会直接影响连接释放的可靠性应优先从连接复用上解决问题。顺带提一句Linux 内核转网络栈里的tcp_tw_reuse相关能力它只对发起连接的一端有效而且依赖时间戳选项。这些内容面试偶尔会问到但实际工作中没有深入了解不建议动这些内核参数。8.2 不要轻视协议的每一条设计TCP 的每个字段、每个状态几乎都是针对真实网络问题设计出来的。比如序列号的设计是为了处理乱序和重复窗口字段是为了流控TIME_WAIT是为了防止迟到的报文串扰新连接。如果你把这三者联系起来看会比孤立背“三次握手四次挥手”得到的信息量高一个量级。做网络和系统编程的朋友我强烈建议你找个周末做一件事本地起两个 Python 进程用 tcpdump 抓包把整个连接生命周期的报文段逐条分析一遍。做完这个实验再去面试再遇到“简述 TCP 三次握手以及四次挥手的流程”你大概率会直接在草稿纸上画出真实的报文序列面试官想不给你过都难。8.3 面试中的最后一问可否用 UDP 实现类似握手有些面试官在你答完 TCP 握手后会追加一个问题如果让你基于 UDP 模拟一个类似三次握手的可靠连接逻辑你会怎么设计状态机这个问题看似超纲实际上是考察你能不能把 TCP 的设计原理迁移到新场景里。我的思路是这样的UDP 没有内核级的连接状态所有“连接”都要在应用层维护。首先定义一个连接 ID 标识对端其次设计一个状态枚举等待 SYN、等待 ACK、已连接再给报文加上SYN、ACK、FIN之类的标志位和序列号字段。剩下的问题就和 TCP 的报文解析逻辑几乎一样了——校验序列号、处理重复报文、确认超时重传。你会发现TCP 的握手协议本质上是一套通用的可靠通信约定和具体传输层实现在一定程度上是可以解耦的。这也是 TCP/IP 协议栈最有意思的地方一层一层剥开底层不过是“把数据正确地、且尽量高效地送到对端”这个朴素问题的一套精妙回答。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

快速静态定位:地质测量中精度与效率兼得的GNSS技术 2026/10/1 4:31:10

快速静态定位:地质测量中精度与效率兼得的GNSS技术

简介:这是一份面向测绘工程、地质勘查及工程测量技术人员的GPS快速静态定位技术应用文献,内容源自《甘肃科技》期刊论文,篇幅精炼但覆盖完整。全文从GPS快速静态定位的基本原理讲起,说明其利用多台GPS接收机同步观测卫星信号、解算…

阅读更多 →
STM32+FPGA工业控制器分级存储方案与选型实战 2026/10/1 4:31:03

STM32+FPGA工业控制器分级存储方案与选型实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
HBuilderX云打包APK报错zipalign failed:完整排查与解决指南 2026/10/1 4:31:03

HBuilderX云打包APK报错zipalign failed:完整排查与解决指南

作为一个长期用HBuilderX做uni-app开发的人,前几天我在云打包安卓APK的时候又踩了一次这个坑——提示Apk zipalign failed。第一次遇到这个错误的人可能会很慌,日志信息就那么一句话,既没有告诉你哪个文件出错,也不说明具体原因。…

阅读更多 →
2021-2026中短波发射机技术演进与固态化选型指南 2026/10/1 4:31:03

2021-2026中短波发射机技术演进与固态化选型指南

这几年的中短波广播发射机市场,表面上风平浪静,内部其实已经换了半代血。从2021年到2026年,Nautel、Ampegon、GatesAir、Thomson Broadcast这几家老牌厂商陆续把固态化、数字化、网络化的技术推到了新的高度,老一代真空管和模拟脉…

阅读更多 →
海光K100深度解析:一颗x86 CPU如何通吃云边端 2026/10/1 4:31:03

海光K100深度解析:一颗x86 CPU如何通吃云边端

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
一文搞懂 IoT 通信模型:D2C/D2D/D2G 与 MQTT 实战剖析 2026/10/1 4:31:03

一文搞懂 IoT 通信模型:D2C/D2D/D2G 与 MQTT 实战剖析

1. 先理清 IoT 通信模式的底子1.1 三种基本模型长什么样,解决什么问题做物联网这块时间久了,你会发现不管是智能家居、工业采集、车联网还是农业监控,所有系统里设备之间通信的底层逻辑翻来覆去就那么几种。D2C、D2D、D2G,加上一个…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉