后端网络【免费下载链接】swift-nioEvent-driven network application framework for high performance protocol servers clients, non-blocking.项目地址https://gitcode.com/gh_mirrors/sw/swift-nio点击查看免费下载SwiftNIO 官方示例NIOTCPEchoServer是一个最精简的 TCP 回显echo服务端它将客户端发来的数据原样返回但代码中浓缩了 SwiftNIO 2.x 时代推荐的整套现代编程模式——ServerBootstrap绑定、pipeline 编解码、NIOAsyncChannel结构化并发封装以及用withThrowingDiscardingTaskGroup管理海量连接的内存安全细节。读完本文你能独立读懂这个示例的每一行代码掌握从仓库根目录一键启动服务并用配套客户端验证的完整流程并理解其中每个关键 API 背后的设计动机。示例定位与快速启动NIOTCPEchoServer的定位在 Sources/NIOTCPEchoServer/README.md 中一句话说明这是一个把客户端发来的任何内容原样发回去的简单 TCP 服务器。启动方式同样由该文档给出在仓库根目录下执行swift run NIOTCPEchoServer服务启动后官方推荐的验证方式是运行配套的 NIOTCPEchoClientswift run NIOTCPEchoClient客户端会建立多条连接、发送消息并等待回显响应二者配合构成一个最小可闭环的端到端 demo。在构建层面Package.swift 将其声明为一个可执行目标仅依赖NIOPosix和NIOCore两个产品库README.md被显式 exclude 于编译之外.executableTarget( name: NIOTCPEchoServer, dependencies: [ NIOPosix, NIOCore, ], exclude: [README.md], swiftSettings: swiftSettings ),这一依赖面本身就是一个信号一个生产级 TCP 服务所需的网络原语只需要 NIOCore核心抽象加 NIOPosixPOSIX 平台实现两个模块即可承载。适用前提Server.swift的入口类型标注了available(macOS 14, iOS 17, tvOS 17, watchOS 10, *)。由于 Linux 平台不受该available列表约束*兜底在 Linux 上运行需要工具链支持 Swift 结构化并发与NIOAsyncChannel的稳定 API 即可而 Apple 平台则需要 macOS 14 / iOS 17 及以上。服务端整体架构三段式数据流完整实现见 Sources/NIOTCPEchoServer/Server.swift。整个服务由三层结构组成理解这条链路是读懂示例的关键传输层ServerBootstrap负责监听 socketaccept 到每个新连接后创建ChildChannel编解码层pipeline 中安装两个 handler负责把字节流按\n拆分为String消息解码再把String消息追加\n写回字节流编码业务层NIOAsyncChannelString, String把 channel 包装为 async/await 风格的入站AsyncSequence与出站 writer业务代码直接以for try await消费消息。对应的核心代码骨架如下摘自 Server.swiftfunc run() async throws { let channel try await ServerBootstrap(group: self.eventLoopGroup) .serverChannelOption(.socketOption(.so_reuseaddr), value: 1) .bind(host: self.host, port: self.port) { channel in channel.eventLoop.makeCompletedFuture { try channel.pipeline.syncOperations.addHandler(ByteToMessageHandler(NewlineDelimiterCoder())) try channel.pipeline.syncOperations.addHandler(MessageToByteHandler(NewlineDelimiterCoder())) return try NIOAsyncChannel( wrappingChannelSynchronously: channel, configuration: NIOAsyncChannel.Configuration( inboundType: String.self, outboundType: String.self ) ) } } try await withThrowingDiscardingTaskGroup { group in try await channel.executeThenClose { inbound in for try await connectionChannel in inbound { group.addTask { print(Handling new connection) await self.handleConnection(channel: connectionChannel) print(Done handling connection) } } } } }为什么绑定到 localhost:8765 并复用 so_reuseaddrServer.main()中硬编码了服务参数let server Server( host: localhost, port: 8765, eventLoopGroup: .singleton )host: localhost、port: 8765这是 demo 的默认监听地址配套客户端 Client.swift 也硬编码了相同的地址与端口因此两者必须成对启动。eventLoopGroup: .singleton使用 SwiftNIO 提供的全局单例MultiThreadedEventLoopGroup。从 GlobalSingletons.swift 的文档注释可以看到SwiftNIO 为不需要精细控制线程资源的程序提供了单例资源单例的线程数可以在任何单例被使用之前通过NIOEventLoopGroupPreferences相关配置项建议但一旦单例创建后修改会触发崩溃。示例选择单例是为了零配置运行。.serverChannelOption(.socketOption(.so_reuseaddr), value: 1)设置SO_REUSEADDR允许服务在重启时快速重新绑定同一端口避免TIME_WAIT导致的bind失败这是 TCP 服务端几乎必加的选项。bind的 completion 闭包在每个子 channel 创建时被调用注意其中的channel.eventLoop.makeCompletedFuture写法handler 的安装与NIOAsyncChannel的包装必须在 channel 所在 event loop 上同步完成详见下文事件循环约束。换行符编解码NewlineDelimiterCoder字节流本身没有消息边界TCP 是流协议一条消息必须由应用层协议定义。本示例用\n作为分隔符NewlineDelimiterCoder同时实现了ByteToMessageDecoder和MessageToByteEncoderprivate final class NewlineDelimiterCoder: ByteToMessageDecoder, MessageToByteEncoder { typealias InboundIn ByteBuffer typealias InboundOut String private let newLine UInt8(ascii: \n) func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws - DecodingState { let readableBytes buffer.readableBytesView if let firstLine readableBytes.firstIndex(of: self.newLine).map({ readableBytes[..$0] }) { buffer.moveReaderIndex(forwardBy: firstLine.count 1) // Fire a read without a newline context.fireChannelRead(Self.wrapInboundOut(String(buffer: ByteBuffer(firstLine)))) return .continue } else { return .needMoreData } } func encode(data: String, out: inout ByteBuffer) throws { out.writeString(data) out.writeInteger(self.newLine) } }解码侧有两个值得注意的实现细节返回.needMoreData表示当前 buffer 中还没有一个完整消息解码器会等待更多字节到达后被再次调用。这正确处理了半包一条消息分多个 TCP 段到达的场景。返回.continue表示还有数据可继续解析。decode中只消费第一条消息firstLine不含换行符并通过moveReaderIndex(forwardBy: firstLine.count 1)跳过换行符本身然后返回.continue让框架继续用剩余字节调用解码。这天然支持粘包——一次read收到多行时循环解码会依次切出每条消息。编码侧则是对称的把String写入ByteBuffer并追加\n。该 coder 在客户端 Client.swift 中以完全相同的方式被复用客户端文件里有一份独立私有副本双方必须使用同一帧协议这正是协议编解码作为独立 handler 的价值——业务 handler 只看到String完全不知道换行符的存在。NIOAsyncChannel把 pipeline 封装成 async/awaitNIOAsyncChannel(wrappingChannelSynchronously:configuration:)的调用必须发生在 channel 的 event loop 上。从 AsyncChannel.swift 的源码注释可以看到这一约束的原因Thismustbe called on the channels event loop otherwise this init will crash. This is necessary because we must install the handlers before any other event in the pipeline happens otherwise we might drop reads.即异步 handler 的安装必须先于 pipeline 中任何其他事件发生否则会丢失读事件。示例中makeCompletedFuture闭包恰好运行在 event loop 内因此wrappingChannelSynchronously在此是安全且同步的。包装后的NIOAsyncChannelString, String配置了inboundType: String.self与outboundType: String.self意味着入站流吐出String、出站 writer 接受String——类型即协议编译器保证消息与 codec 约定一致。从 AsyncChannel.swift 中Configuration的定义还可以了解到两个示例未显式设置、但有默认值的配置项实际项目中可按需调整backPressureStrategy入站流的背压策略默认是高低水位策略HighLowWatermark(lowWatermark: 2, highWatermark: 10)。当入站消息积压超过高水位时暂停底层读取回落到低水位后恢复防止慢消费者拖垮内存isOutboundHalfClosureEnabled默认false若开启则出站 writer 结束或释放时触发出站半关闭发送 FIN 但保留接收适用于需要优雅写关闭的长连接协议。executeThenClose是推荐的作用域 API在闭包内使用入站流与出站 writer闭包退出后 channel 自动关闭。这与早期需要手动管理channel.close()的生命周期相比把资源必然释放变成了语言结构层面的保证。连接级任务管理为什么必须用 discarding task group服务端的连接分发逻辑是这段示例中最容易被忽略、也最容易被写错的部分try await withThrowingDiscardingTaskGroup { group in try await channel.executeThenClose { inbound in for try await connectionChannel in inbound { group.addTask { print(Handling new connection) await self.handleConnection(channel: connectionChannel) print(Done handling connection) } } } }每个NIOAsyncChannel即一条客户端连接都在group.addTask中开一个子任务处理。源码注释直接点明了为什么必须使用withThrowingDiscardingTaskGroup而不是普通的withThrowingTaskGroupIt is important to use a discarding task group here which automatically discards finished child tasks. A normal task group retains all child tasks and their outputs in memory until they are consumed by iterating the group or by exiting the group. Since, we are never consuming the results of the group we need the group to automatically discard them; otherwise, this would result in a memory leak over time.也就是说普通 task group 会把所有已结束子任务及其返回值保留在内存中直到被迭代消费或 group 退出本场景中连接是无限流子任务结果永远不会被消费若用普通 group服务运行越久内存占用越大——对长期运行的服务端而言这是一条必须遵守的准则。注意外层channel.executeThenClose消费的是server channel 的入站流每 accept 一个新连接就产出一个NIOAsyncChannel循环随服务关闭而自然结束整个run()的退出路径也因此是确定性的。单连接处理与故障隔离连接处理逻辑独立在handleConnection中它体现了单条连接的异常不得拖垮整个服务的设计private func handleConnection(channel: NIOAsyncChannelString, String) async { // Note that this method is non-throwing and we are catching any error. // We do this since we dont want to tear down the whole server when a single connection // encounters an error. do { try await channel.executeThenClose { inbound, outbound in for try await inboundData in inbound { print(Received request (\(inboundData))) try await outbound.write(inboundData) } } } catch { print(Hit error: \(error)) } }方法签名无throws内部do/catch捕获全部错误。对比外层的withThrowingDiscardingTaskGroup异常会向上传播并终止服务这里的吞错是故意的某个客户端异常断开或协议出错时只打印日志并结束该连接不影响其他连接与服务本身。回显逻辑本身只有两行for try await inboundData in inbound逐条消费消息try await outbound.write(inboundData)原样写回。outbound.write是 await 的天然受背压约束——如果下游写得太慢socket 缓冲已满写入会挂起而不是无限缓冲。连接何时结束当客户端发送 FIN出站半关闭导致入站流结束时for循环退出executeThenClose关闭整个 channel。端到端验证配套客户端的行为验证服务是否工作运行 NIOTCPEchoClientswift run NIOTCPEchoClient从 Client.swift 可以看到客户端的具体行为func run() async throws { try await withThrowingTaskGroup(of: Void.self) { group in for i in 0...20 { group.addTask { try await self.sendRequest(number: i) } } try await group.waitForAll() } }一次性并发发起21 个连接0...20每个连接发送Hello on connection N收到一条回显后即break退出循环退出循环后NIOAsyncChannel引用被释放连接自动关闭——客户端注释明确说明once we exit out of this loop and the references to the NIOAsyncChannel are dropped the connection is going to close itself与 server 端刻意使用 discarding group 不同这里使用普通withThrowingTaskGroupwaitForAll()是恰当的因为所有子任务完成后任务就结束了不存在累积问题。server 与 client 的完整配合链路为clientClientBootstrap.connect→ server accept 并进入for try await connectionChannel in inbound→ 双方 pipeline 中各自的NewlineDelimiterCoder完成编解码 → serveroutbound.write(inboundData)回显 → client 打印响应并关闭。小结NIOTCPEchoServer虽然只有百行代码却完整覆盖了用 SwiftNIO 编写现代 TCP 服务的关键决策点关注点示例做法依据服务启动ServerBootstrapso_reuseaddrlocalhost:8765Server.swift消息分帧NewlineDelimiterCoder同时实现解码.needMoreData/.continue与编码Server.swift并发模型NIOAsyncChannelexecuteThenClose作用域 APIAsyncChannel.swift连接管理withThrowingDiscardingTaskGroup防止子任务累积导致内存泄漏Server.swift故障隔离单连接do/catch异常不传播至服务层Server.swift端到端验证配套NIOTCPEchoClient并发 21 连接验证回显Client.swift如果要在此基础上扩展真实业务更换帧协议、持久化事件循环组、调整背压水位都可以直接在Server.swift的对应位置修改而无需改变整体结构——这正是官方示例保持如此简练的原因它示范的不是一个 echo 服务而是 SwiftNIO 2.x 时代编写网络服务的标准姿势。赞分享后端网络【免费下载链接】swift-nioEvent-driven network application framework for high performance protocol servers clients, non-blocking.项目地址https://gitcode.com/gh_mirrors/sw/swift-nio点击查看免费下载相关推荐swift-nio NIOTCPEchoClient 详解基于 Swift 并发async/await的 TCP 回显客户端实战swift nio NIOTCPEchoClient 详解基于 Swift 并发async/await的 TCP 回显客户端实战 本文以 NIOTCPEc后端网络Tornado TCP Echo 实战用 TCPServer 与 TCPClient 构建异步流式服务Tornado TCP Echo 实战用 TCPServer 与 TCPClient 构建异步流式服务 导读 Tornado 不仅是 Web 框架其底层还提后端Web框架异步编程WebSocketQuick 框架中的 Async/Await基于 AsyncSpec 编写 Swift 并发测试Quick 框架中的 Async/Await基于 AsyncSpec 编写 Swift 并发测试 本指南围绕 Quick 测试框架的 Async/Await测试开发工具上一篇Chameleon框架与Core Animation结合高性能渐变动画实现下一篇PhotoGIMP让Photoshop用户无缝切换到开源图像编辑的完美方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
Volatility内存取证实战指南:从安装到恶意代码分析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 3:13:12
JNA 默认类型映射全解析:Native 与 Java 类型对照、平台差异与自定义映射实战 系统编程后端 【免费下载链接】jna Java Native Access 项目地址: https://gitcode.com/gh_mirrors/jn/jna 点击查看 免费下载 导读
本文基于 www/Mappings.md 展开,系统讲解 JNA(Java Native Access)中 Java 类型与原生 C 类型… · 2026/9/25 3:13:12
Agent-Reach 更新日志深度解读:从版本演进看多渠道接入、登录态判定与反爬对抗的工程实践 人工智能AI AgentMCP 服务AI 技能CLI 【免费下载链接】Agent-Reach 给你的 AI Agent 一键装上互联网能力。13 个平台(网页/GitHub/YouTube/小红书/B站/Twitter/Reddit 等)多后端路由,当下最稳的接入方式替你选好、装好、体检好。GitHub 主仓库… · 2026/9/25 3:13:12
GEO全场景智能生态:全栈隐私计算与绿色低碳规模化落地实践 GEO这个缩写,去年在圈内还属于小范围讨论的概念,今年已经高频出现在各类招标书和企业战略PPT里。从热搜词的密集程度就能感受到风向的变化:GEO优化、GEO服务商、GEO投毒攻击、GEO数据结构、GEO招标项目……说明大量企业已经越过“要不要做GEO… · 2026/9/25 3:45:38
基于Spring Boot的美食推荐系统实战:协同过滤与部署全解析 民以食为天,但"吃什么"这个问题,每天都要消耗大量决策时间。2023年我做了一个基于Spring Boot的美食推荐系统,初衷很简单:不想再让用户面对几百道菜翻来翻去无从下手,而是根据每个人的口味偏好、历史行为&am… · 2026/9/25 3:45:38
基于SVM的降水量预测模型实战:SVR回归、特征构造与调参要点 简介:一套基于支持向量机(SVM)的降水量预测模型代码包,面向机器学习、人工智能及数据挖掘方向的初学者和研究人员,可用于算法复现、实验对比和毕业设计参考。资源内共 54 个文件,以 26 个 .m 主程序为核心&… · 2026/9/25 3:45:38
5个可落地的免费AI Agent工作流实战指南 1. 这不是工具清单,而是一套可落地的“时间置换系统” “5个免费AI Agent,让我每天省出3小时”——这句话乍看像标题党,但背后藏着一个被多数人忽略的事实:我们真正缺的从来不是工具,而是把AI从“玩具”变成“同事”的… · 2026/9/25 3:45:38
Spring Boot酒店客房管理系统:源码+论文打造完整毕设 简介:酒店客房管理系统毕业设计资料,包含完整源码与论文,面向Java Web课程设计或毕设开发人员,同时也适合需要搭建酒店管理场景的初学者。系统覆盖客房信息管理、客房清扫管理、用户入住管理、会员管理、收藏客房等核心业务&#… · 2026/9/25 3:45:32
STM32F107+LAN8720A以太网调试指南:从CubeMX到LWIP完整流程 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 3:45:26
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37