
文档知识库教程OpenHarmony【免费下载链接】CangjieCorpus本仓库为仓颉编程语言语料库聚焦 仓颉编程语言 核心知识体系整合官方开发指南、API 文档、典型代码示例及语法规范等多维度资源经结构化处理与专业标注构建为支持 RAG检索增强生成技术 的高质量知识基座适配智能编码助手、学习辅助工具等应用开发需求。 欢迎开发者基于本语料库构建仓颉语言智能应用推动鸿蒙开发生态智能化升级项目地址https://gitcode.com/Cangjie/CangjieCorpus点击查看免费下载导读本文以仓颉标准库std.net网络编程包中的 UDP 使用示例udp.md为主体讲解如何使用UdpSocket完成无连接的数据报收发从套接字创建、绑定、报文收发、地址解析到超时控制与线程协同并深入剖析 UdpSocket 的底层 API 设计与其所属的 DatagramSocket 接口体系。读者读完本文后可以独立编写一个可运行的单机 UDP 服务端/客户端程序并理解 UDP 报文收发模型与 TCP 流式传输的本质差异。UDP 协议与 std.net 中的 Socket 体系UDPUser Datagram Protocol用户数据报协议是一种无连接的传输协议。它不提供可靠性和流量控制但具有较低的延迟和较小的网络开销主要用于视频直播、在线游戏等实时性要求高的应用场景详见 net_package_overview.md。std.net包同时支持 UDP/TCP/UDS 三种 Socket 类型其类继承关系如下Hierarchy Resource ├StreamingSocket │ ├TcpSocket │ └UnixSocket │ ├DatagramSocket │ ├UdpSocket │ └UnixDatagramSocket │ └ServerSocket ├TcpServerSocket └UnixServerSocket从继承关系可以清晰地看出UDP 对应的UdpSocket归属于DatagramSocket数据报套接字分支与TcpSocket所属的StreamingSocket流式套接字分支并列。这种架构从类型层面就区分了面向报文与面向流两类网络模型。DatagramSocket 接口报文收发的基本契约UdpSocket的父接口DatagramSocket定义了数据报套接字的核心能力见 net_package_interfaces.mdpublic interface DatagramSocket : Resource ToString { prop localAddress: SocketAddress prop remoteAddress: ?SocketAddress mut prop receiveTimeout: ?Duration mut prop sendTimeout: ?Duration func receiveFrom(buffer: ArrayByte): (SocketAddress, Int64) func sendTo(address: SocketAddress, payload: ArrayByte): Unit }从接口定义可以提炼出数据报传输的几条关键语义数据包边界保持数据包大小在发送端决定一端发送了 10 字节和 15 字节的报文对端将收到相同大小的对应报文不会像 TCP 那样发生字节流重组传输不可靠数据包传输不保证顺序、不保证送达也允许空数据包存在单包大小上限UDP 套接字一次可以处理最大 64KB 的数据包收发需要地址receiveFrom返回(SocketAddress, Int64)二元组同时给出报文来自哪个地址与收取了多少字节sendTo则需要显式传入对端地址。完整示例UDP 服务端与客户端收发 3 字节报文示例源码位于 udp.md它是一个服务端先就绪、客户端后发送的单机 UDP 通信程序import std.net.* import std.sync.* let SERVER_PORT: UInt16 33333 let barrier Barrier(2) func runUdpServer() { try (serverSocket UdpSocket(bindAt: SERVER_PORT)) { serverSocket.bind() barrier.wait() let buf ArrayByte(3, repeat: 0) let (clientAddr, count) serverSocket.receiveFrom(buf) let sender (clientAddr as IPSocketAddress)?.address.toString() ?? // Server receive 3 bytes: [1, 2, 3] from 127.0.0.1 println(Server receive ${count} bytes: ${buf} from ${sender}) } } main(): Int64 { let fut spawn { runUdpServer() } barrier.wait() try (udpSocket UdpSocket(bindAt: 0)) { // random port udpSocket.sendTimeout Duration.second * 2 udpSocket.bind() udpSocket.sendTo( IPSocketAddress(127.0.0.1, SERVER_PORT), [1, 2, 3] ) } fut.get() return 0 }运行结果Server receive 3 bytes: [1, 2, 3] from 127.0.0.1代码结构逐段解析1. 端口与同步原语let SERVER_PORT: UInt16 33333 let barrier Barrier(2)SERVER_PORT是服务端监听端口类型为UInt16端口范围 0~65535Barrier(2)来自std.sync包用于协调主线程与服务端线程同时就绪。Barrier提供协调多个线程一起执行到某一个程序点的功能率先到达的线程进入阻塞当所有线程都到达后才一起继续执行见 sync_package_classes.md。这里替代了sleep轮询等待是更精确的同步手段。2. 服务端创建、绑定、阻塞接收try (serverSocket UdpSocket(bindAt: SERVER_PORT)) { serverSocket.bind() ... let (clientAddr, count) serverSocket.receiveFrom(buf) }UdpSocket(bindAt: SERVER_PORT)构造一个未绑定的套接字实例bindAt!是标签参数可传SocketAddress或UInt16见 net_package_classes.md创建实例后必须调用bind()完成绑定才能在不与远端建连的前提下接收报文receiveFrom是阻塞式调用将报文内容写入buf3 字节缓冲区返回发送端地址与报文大小。buf应选择合适的大小否则报文会被截断且返回值会大于缓冲区大小try (…)是仓颉的资源管理语法块结束时自动调用close()回收套接字。UdpSocket需要被显式close()。3. 发送端地址解析let sender (clientAddr as IPSocketAddress)?.address.toString() ?? receiveFrom返回的clientAddr类型是SocketAddress需要通过as IPSocketAddress向下转型为 IP 套接字地址再取出其中的IPAddress并转成字符串若转型失败则为None用?? 兜底。4. 客户端随机端口 超时 指定地址发送try (udpSocket UdpSocket(bindAt: 0)) { // random port udpSocket.sendTimeout Duration.second * 2 udpSocket.bind() udpSocket.sendTo( IPSocketAddress(127.0.0.1, SERVER_PORT), [1, 2, 3] ) }bindAt: 0表示请求操作系统分配随机空闲端口适用于只管发、不关心从哪个端口发的客户端场景sendTimeout Duration.second * 2设置send/sendTo操作的超时时间。超时时间设置过小会被钳制为最小时钟周期值过大则被钳制为最大超时时间2⁶³-1 纳秒默认值为None永不超时sendTo(IPSocketAddress(127.0.0.1, SERVER_PORT), [1, 2, 3])向目标地址发送 3 字节载荷[1, 2, 3]无需事先建立连接[1, 2, 3]会被自动推断为ArrayByte。5. 线程协同与收尾let fut spawn { runUdpServer() } barrier.wait() ... fut.get()spawn创建仓颉线程执行服务端逻辑见 create_thread.md。仓颉采用抢占式线程模型与M:N线程调度spawn接受无形参 lambda 作为新线程的入口主线程与服务端线程各自调用一次barrier.wait()凑齐 2 个等待者后同时放行保证服务端bind()完成、客户端再开始发送fut.get()等待服务端线程结束避免主线程提前退出导致服务端未打印结果main(): Int64返回 0 表示程序正常结束。UdpSocket 核心 API 纵深解析UdpSocket类的完整定义见 net_package_classes.mdpublic class UdpSocket : DatagramSocket { public init(bindAt!: SocketAddress) public init(bindAt!: UInt16) }构造与生命周期API说明init(bindAt!: SocketAddress)创建一个未绑定的UdpSocket实例绑定地址与端口由SocketAddress指定init(bindAt!: UInt16)创建一个未绑定的UdpSocket实例仅指定绑定端口本机地址自动选择bind(): Unit绑定本地端口。绑定失败后需要close套接字不支持多次重试close(): Unit关闭套接字关闭后除close/isClosed外的所有操作均不允许再调用接口允许多次调用isClosed(): Bool判断套接字是否已通过close显式关闭报文收发API说明receiveFrom(buffer: ArrayByte): (SocketAddress, Int64)接收报文返回发送端地址与实际收取的报文大小可能为 0或大于 buffer 大小。当本机缓存过小无法读取报文时抛SocketException读取超时抛SocketTimeoutExceptionsendTo(recipient: SocketAddress, payload: ArrayByte): Unit发送报文到指定远端地址对端缓存不足时可能被阻塞报文可能被丢弃。payload 超出系统限制、系统发送失败如connect被调用后收到异常 ICMP 报文时抛SocketExceptionreceive(buffer: ArrayByte): Int64从connect连接到的地址收取报文需先建连send(payload: ArrayByte): Unit发送报文到connect连接到的地址需先建连值得注意的是UDP 套接字虽然本质是无连接的但UdpSocket也提供了connect(remote: SocketAddress)/disconnect()接口实现逻辑上的定向通信connect必须在bind之后调用连接后仅接受该远端地址的报文且此时可使用send/receive免地址收发连接后端口会开始接收 ICMP 报文若收到异常报文可能导致send/sendTo执行失败disconnect可取消定向连接可在connect前调用、可多次调用。属性配置属性类型对应系统选项说明localAddressSocketAddress—读取套接字将要或已经绑定的本地地址remoteAddress?SocketAddress—读取已连接的远端地址未连接时返回NonereceiveTimeout?Duration—设置/读取receive/receiveFrom超时默认NonesendTimeout?Duration—设置/读取send/sendTo超时默认NonereceiveBufferSizeInt64SO_RCVBUF设置/读取接收缓冲区size ≤ 0 抛IllegalArgumentExceptionsendBufferSizeInt64SO_SNDBUF设置/读取发送缓冲区size ≤ 0 抛IllegalArgumentExceptionreuseAddressBoolSO_REUSEADDR设置/读取地址复用默认与生效行为取决于系统reusePortBoolSO_REUSEPORTWindows 无此属性访问会抛SocketException此外UdpSocket还提供了底层getSocketOption/setSocketOption系列方法含Bool与IntNative便捷重载可通过level如SOL_SOCKET与option如SO_KEEPALIVE直接操作原生套接字选项。这一底层通道也是 socket_option.md 中增加自定义属性示例的实现基础——示例通过extend TcpSocket配合getSocketOptionIntNative/setSocketOptionIntNative自定义了customNoDelay属性同样的手法可推广到UdpSocket。地址类型IPSocketAddress 与 IPAddress示例中的IPSocketAddress(127.0.0.1, SERVER_PORT)与clientAddr as IPSocketAddress涉及std.net的两类核心地址对象见 net_package_classes.mdIPSocketAddress实现 IP 协议 Socket 地址IP 地址 端口号提供三个构造函数init(address: ArrayByte, port: UInt16)大端序字节数组、init(address: String, port: UInt16)、init(address: IPAddress, port: UInt16)属性addressIPAddress、portUInt16、familyAddressFamily、size原始字节长度静态方法parse(192.168.1.2:8080)、tryParseIPAddressIP 协议地址的抽象基类IPv4Address/IPv6Address提供parse/tryParse/resolve域名解析、isIPv4/isIPv6/isLoopback/isPrivate/isMulticast/isLinkLocal/isGlobalUnicast/isUnspecified等地址分类判断以及getAddressBytes、getPrefix(prefixLen)等字节与子网操作。异常体系UDP 收发可能触及的两类异常见 net_package_exceptions.mdSocketException继承自IOException覆盖绑定失败、缓存不足无法读取报文、系统发送失败等套接字相关错误SocketTimeoutException继承自Exception在receiveFrom/sendTo超过设定的receiveTimeout/sendTimeout时抛出便于实现带超时的收发逻辑。UDP 编程模型与 TCP 的对照std.net官方 Socket 指南net_socket.md对两种场景给出了明确的编程模型对比UDP不可靠传输编程模型创建套接字并指定本端绑定地址执行绑定指定远端地址进行报文发送不连接远端地址场景下可以收取来自不同远端地址的报文并返回远端地址信息。TCP可靠传输编程模型对照参考创建服务端套接字指定本端绑定地址执行绑定执行accept阻塞等待客户端连接创建客户端套接字指定远端连接地址执行连接连接成功后服务端在accept返回新套接字双方通过该套接字读写。两者的本质区别在于TCP 是面向连接 字节流必须先建连再收发数据无边界UDP 是无连接 数据报绑定即可收发每个报文自带边界、携带对端地址。这也是UdpSocket归属于DatagramSocket、而TcpSocket归属于StreamingSocket的原因。仓颉并发文档concurrency_overview.md也提示了一个 UDP 场景相关的注意事项仓颉采用M:N线程模型当仓颉线程调用socket等可能阻塞的 foreign 函数时会直接阻塞承载它的 native 线程。因此在 UDP 服务端中把阻塞式receiveFrom放入spawn的子线程执行如示例所示可以让主线程继续执行其他逻辑避免整程序吞吐量下降。实战要点与扩展方向报文大小边界UDP 单报文最大 64KB发送前应确保 payload 不超过该上限接收方缓冲区应预置足够大小否则报文将被截断同步替代轮询示例用Barrier(2)保证服务端已绑定、客户端再发送相比 sleep 固定时长更稳定仓颉还提供SyncCounter、Channel等同步原语参见 TCP 示例 中SyncCounter(1)waitUntilZero()的用法收包来源解析receiveFrom返回的SocketAddress需向下转型为IPSocketAddress才能读取发送方 IP 与端口这在高并发多客户端 UDP 服务中尤其关键——不同客户端的数据可能来自不同地址定向连接优化若通信对象固定可先connect再使用send/receive免去每次携带目标地址但注意connect会过滤掉其他来源的报文同族参考std.net还提供UnixDatagramSocket基于数据包的本机进程间通信不支持 Windows其收发模型与UdpSocket一致可参考 unix_datagram.md 对照学习运行验证示例代码可直接编译运行cjc编译后在本机执行输出Server receive 3 bytes: [1, 2, 3] from 127.0.0.1即表示收发链路正常。参考文档索引UDP 使用示例本文主体std.net 包总览UdpSocket 类完整 APIDatagramSocket 接口定义IPSocketAddress / IPAddress 地址体系Socket 编程指南UDP/TCP 模型对照Barrier 同步原语仓颉线程创建套接字属性配置与自定义选项赞分享文档知识库教程OpenHarmony【免费下载链接】CangjieCorpus本仓库为仓颉编程语言语料库聚焦 仓颉编程语言 核心知识体系整合官方开发指南、API 文档、典型代码示例及语法规范等多维度资源经结构化处理与专业标注构建为支持 RAG检索增强生成技术 的高质量知识基座适配智能编码助手、学习辅助工具等应用开发需求。 欢迎开发者基于本语料库构建仓颉语言智能应用推动鸿蒙开发生态智能化升级项目地址https://gitcode.com/Cangjie/CangjieCorpus点击查看免费下载相关推荐仓颉语言 Socket 编程实战基于 std.net 的 TCP 与 UDP 套接字开发指南仓颉语言 Socket 编程实战基于 std.net 的 TCP 与 UDP 套接字开发指南 本指南以仓颉标准库 std.net 中的套接字Socket编文档编程语言仓颉 std.net 网络编程类库全解析IP 地址、Socket 地址与 TCP/UDP/UDS 套接字实战指南仓颉 std.net 网络编程类库全解析IP 地址、Socket 地址与 TCP/UDP/UDS 套接字实战指南 导读 本文以仓颉编程语言标准库 std.ne文档知识库教程OpenHarmony仓颉编程语言 std.net 套接字属性配置与自定义扩展实战TcpSocket 选项调优指南仓颉编程语言 std.net 套接字属性配置与自定义扩展实战TcpSocket 选项调优指南 本文基于仓颉标准库 std.net 的官方示例文档系统讲解如何文档知识库教程OpenHarmony上一篇如何一次性通过 WCAG 2.2 无障碍审计web-quality-skills 的 40 条 a11y 规则速查清单下一篇Apache Mesos 代码格式化指南ClangFormat 配置、编辑器集成与风格对齐实践创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考