终极指南:5步掌握ENet可靠UDP网络库实战应用

发布时间:2026/8/10 19:37:28

终极指南:5步掌握ENet可靠UDP网络库实战应用
终极指南5步掌握ENet可靠UDP网络库实战应用【免费下载链接】enetENet reliable UDP networking library项目地址: https://gitcode.com/gh_mirrors/en/enetENet是一个轻量级、高性能的可靠UDP网络库专为实时多人游戏和网络应用设计。这个可靠的UDP网络库提供了跨平台网络开发能力让开发者能够轻松构建高性能的网络通信系统。如果你正在寻找一个既能保证数据可靠传输又能保持UDP低延迟特性的网络解决方案ENet绝对是你的不二选择为什么选择ENet游戏开发者的网络利器在实时网络编程的世界里我们常常面临一个经典困境TCP太慢UDP太不可靠。TCP虽然保证了数据的可靠传输但其拥塞控制和重传机制带来了显著的延迟而UDP虽然速度快却无法保证数据包的顺序和可靠性。ENet可靠UDP网络库完美解决了这个矛盾它建立在UDP协议之上通过智能的可靠性机制、序列化和拥塞控制为开发者提供了鱼与熊掌兼得的解决方案。想象一下你既能享受UDP的低延迟又能获得TCP的可靠性保障这就是ENet的魅力所在ENet的核心优势真正的跨平台支持从Linux到Windows从macOS到嵌入式系统ENet都能完美运行极致的性能优化专为实时应用设计延迟极低吞吐量高简单易用的API相比直接使用socket编程ENet提供了更高级、更友好的接口自动拥塞控制智能管理网络流量避免网络拥堵开源免费MIT许可证商业友好可以放心在商业项目中使用快速上手5分钟搭建你的第一个ENet应用准备好了吗让我们马上开始ENet的实战之旅首先你需要获取ENet的源代码。打开终端执行以下命令git clone https://gitcode.com/gh_mirrors/en/enet cd enetENet提供了多种构建方式我推荐使用CMake这是最现代、最跨平台的构建工具mkdir build cd build cmake .. make编译完成后你会看到生成的libenet.a静态库文件。这就是ENet的核心库包含了所有网络通信功能。现在让我们创建一个简单的服务器程序。在你的项目中包含ENet头文件#include enet/enet.h #include stdio.h #include stdlib.h int main() { // 初始化ENet库 if (enet_initialize() ! 0) { fprintf(stderr, ENet初始化失败\n); return EXIT_FAILURE; } atexit(enet_deinitialize); // 创建服务器主机 ENetAddress address; address.host ENET_HOST_ANY; // 监听所有网络接口 address.port 12345; // 使用12345端口 ENetHost* server enet_host_create(address, 32, 2, 0, 0); if (server NULL) { fprintf(stderr, 无法创建服务器主机\n); return EXIT_FAILURE; } printf(ENet服务器已启动正在监听端口 12345...\n); // 主事件循环 ENetEvent event; while (1) { // 等待事件超时设置为1000毫秒 while (enet_host_service(server, event, 1000) 0) { switch (event.type) { case ENET_EVENT_TYPE_CONNECT: printf(新客户端连接\n); break; case ENET_EVENT_TYPE_RECEIVE: printf(收到消息%.*s\n, (int)event.packet-dataLength, event.packet-data); enet_packet_destroy(event.packet); break; case ENET_EVENT_TYPE_DISCONNECT: printf(客户端断开连接\n); break; } } } enet_host_destroy(server); return 0; }编译这个服务器程序时记得链接ENet库gcc server.c -lenet -o server试试运行它你会看到服务器开始监听端口等待客户端连接。这就是ENet的强大之处——用不到50行代码就实现了一个功能完整的网络服务器✨ENet架构解析理解可靠UDP的魔法要真正掌握ENet我们需要了解它的核心架构。ENet的设计哲学是简单而强大它通过几个关键组件实现了可靠的UDP通信1. 主机Host管理在ENet中ENetHost是网络通信的核心。每个主机可以同时作为服务器和客户端这种设计让点对点通信变得异常简单。主机负责管理所有网络连接、处理数据包发送和接收。2. 对等体Peer连接ENetPeer代表一个网络连接的对端。无论是服务器还是客户端都通过Peer对象进行通信。ENet会自动维护连接状态、处理心跳包、管理超时重连。3. 数据包Packet系统ENet的数据包系统非常灵活可靠数据包保证按顺序送达支持重传不可靠数据包不保证送达但延迟最低无序可靠数据包保证送达但不保证顺序数据包分片自动处理大数据包的分片和重组4. 通道Channel机制这是ENet最聪明的设计之一ENet支持多个独立的通信通道每个通道都有自己的序列号。这意味着通道0上的可靠数据包不会阻塞通道1上的数据游戏可以同时发送位置更新通道0和聊天消息通道1不同优先级的数据可以在不同通道上传输看看ENet的源码结构你会发现它的设计非常清晰include/enet/enet.h- 主头文件包含所有公共APIhost.c- 主机管理核心逻辑peer.c- 对等体连接管理packet.c- 数据包处理protocol.c- 通信协议实现unix.c/win32.c- 平台特定实现实战演练构建高性能游戏聊天系统让我们通过一个实际的例子来展示ENet的强大功能。我们将构建一个简单的游戏聊天系统支持可靠的消息传输和低延迟的玩家位置同步。服务器端实现// chat_server.c #include enet/enet.h #include stdio.h #include string.h #include stdlib.h #define MAX_PLAYERS 100 #define CHAT_CHANNEL 0 #define POSITION_CHANNEL 1 typedef struct { ENetPeer* peer; char username[32]; float x, y, z; } Player; Player players[MAX_PLAYERS]; int player_count 0; void broadcast_chat(const char* message, ENetHost* server, ENetPeer* exclude) { ENetPacket* packet enet_packet_create(message, strlen(message) 1, ENET_PACKET_FLAG_RELIABLE); for (int i 0; i player_count; i) { if (players[i].peer ! exclude) { enet_peer_send(players[i].peer, CHAT_CHANNEL, packet); } } // 注意不要在这里销毁packet因为多个peer共享同一个packet // enet_packet_destroy(packet); } int main() { if (enet_initialize() ! 0) { fprintf(stderr, ENet初始化失败\n); return 1; } atexit(enet_deinitialize); ENetAddress address; address.host ENET_HOST_ANY; address.port 7777; ENetHost* server enet_host_create(address, 32, 2, 0, 0); if (!server) { fprintf(stderr, 无法创建服务器\n); return 1; } printf(游戏聊天服务器已启动 (端口: 7777)\n); ENetEvent event; while (1) { while (enet_host_service(server, event, 100) 0) { switch (event.type) { case ENET_EVENT_TYPE_CONNECT: { printf(新玩家连接: %x:%u\n, event.peer-address.host, event.peer-address.port); // 发送欢迎消息 const char* welcome 欢迎来到游戏聊天室; ENetPacket* packet enet_packet_create(welcome, strlen(welcome) 1, ENET_PACKET_FLAG_RELIABLE); enet_peer_send(event.peer, CHAT_CHANNEL, packet); // 添加玩家到列表 if (player_count MAX_PLAYERS) { players[player_count].peer event.peer; players[player_count].x 0; players[player_count].y 0; players[player_count].z 0; player_count; } break; } case ENET_EVENT_TYPE_RECEIVE: { // 根据通道处理不同数据 if (event.channelID CHAT_CHANNEL) { printf(收到聊天消息: %s\n, event.packet-data); broadcast_chat(event.packet-data, server, event.peer); } else if (event.channelID POSITION_CHANNEL) { // 处理位置更新 printf(收到位置更新\n); // 这里可以广播给其他玩家 } enet_packet_destroy(event.packet); break; } case ENET_EVENT_TYPE_DISCONNECT: { printf(玩家断开连接\n); // 从玩家列表中移除 for (int i 0; i player_count; i) { if (players[i].peer event.peer) { players[i] players[--player_count]; break; } } break; } } } } enet_host_destroy(server); return 0; }客户端实现// chat_client.c #include enet/enet.h #include stdio.h #include string.h #include stdlib.h #include pthread.h void* receive_thread(void* arg) { ENetHost* client (ENetHost*)arg; ENetEvent event; while (1) { while (enet_host_service(client, event, 100) 0) { switch (event.type) { case ENET_EVENT_TYPE_RECEIVE: printf(服务器: %s\n, event.packet-data); enet_packet_destroy(event.packet); break; case ENET_EVENT_TYPE_DISCONNECT: printf(与服务器断开连接\n); return NULL; } } } return NULL; } int main(int argc, char** argv) { if (argc ! 2) { printf(用法: %s 服务器IP\n, argv[0]); return 1; } if (enet_initialize() ! 0) { fprintf(stderr, ENet初始化失败\n); return 1; } atexit(enet_deinitialize); ENetHost* client enet_host_create(NULL, 1, 2, 0, 0); if (!client) { fprintf(stderr, 无法创建客户端\n); return 1; } ENetAddress address; enet_address_set_host(address, argv[1]); address.port 7777; ENetPeer* server enet_host_connect(client, address, 2, 0); if (!server) { fprintf(stderr, 无法连接到服务器\n); enet_host_destroy(client); return 1; } // 等待连接建立 ENetEvent event; if (enet_host_service(client, event, 5000) 0 event.type ENET_EVENT_TYPE_CONNECT) { printf(成功连接到服务器\n); } else { enet_peer_reset(server); printf(连接超时\n); enet_host_destroy(client); return 1; } // 创建接收线程 pthread_t thread; pthread_create(thread, NULL, receive_thread, client); // 主线程处理用户输入 char message[256]; while (1) { printf( ); fgets(message, sizeof(message), stdin); message[strcspn(message, \n)] 0; // 移除换行符 if (strcmp(message, quit) 0) { break; } ENetPacket* packet enet_packet_create(message, strlen(message) 1, ENET_PACKET_FLAG_RELIABLE); enet_peer_send(server, 0, packet); } // 断开连接 enet_peer_disconnect(server, 0); // 等待断开完成 while (enet_host_service(client, event, 3000) 0) { if (event.type ENET_EVENT_TYPE_DISCONNECT) { printf(已断开连接\n); break; } } pthread_join(thread, NULL); enet_host_destroy(client); return 0; }这个示例展示了ENet在实际应用中的强大功能。你发现了什么是的我们使用了两个独立的通道通道0用于可靠的聊天消息通道1用于低延迟的位置更新。这种设计确保了聊天消息的可靠性同时保持了游戏位置更新的实时性性能优化与最佳实践ENet虽然强大但要发挥其最大性能还需要一些技巧。让我分享几个实战经验1. 合理设置缓冲区大小// 创建主机时指定带宽限制 ENetHost* host enet_host_create(address, 32, // 最大连接数 2, // 通道数 57600, // 下行带宽 (56kbps) 12800); // 上行带宽 (12.8kbps)根据你的网络环境设置合适的带宽限制ENet会自动进行拥塞控制。如果设置为0ENet会假设带宽无限这可能在实际网络环境中导致问题。2. 选择合适的包标志ENet提供了多种包标志根据需求选择ENET_PACKET_FLAG_RELIABLE- 可靠传输保证送达ENET_PACKET_FLAG_UNSEQUENCED- 无序可靠传输ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT- 不可靠分片传输黄金法则对关键数据使用可靠传输对实时性要求高的数据使用不可靠传输。3. 多通道策略充分利用ENet的多通道特性通道0关键控制消息登录、登出、重要状态变更通道1游戏状态同步位置、旋转等通道2聊天消息、通知通道3文件传输、大块数据4. 心跳与超时设置// 设置连接超时和心跳间隔 enet_peer_timeout(peer, 32, // 超时限制 1000, // 最小超时 5000); // 最大超时合理的超时设置可以快速检测到断开的连接同时避免误判。跨平台部署实战ENet的真正优势在于其出色的跨平台能力。无论你的目标平台是什么ENet都能提供一致的API体验。Linux/macOS构建# 使用autotools传统方式 autoreconf -vfi ./configure make sudo make install # 使用CMake推荐 mkdir build cd build cmake .. makeWindows构建ENet为Windows提供了完整的支持。查看win32.c文件你会发现ENet已经处理了所有Windows特有的网络API。Visual Studio用户直接使用项目中的enet.dsp文件或者使用CMake生成VS解决方案cmake .. -G Visual Studio 16 2019MinGW用户gcc -c *.c -Iinclude ar rcs libenet.a *.o嵌入式系统ENet的轻量级设计使其非常适合嵌入式系统。它的内存占用小没有外部依赖可以轻松移植到各种嵌入式平台。常见问题与解决方案在实际使用ENet时你可能会遇到一些问题。别担心这里有一些常见问题的解决方案1. 编译错误enet.h: No such file or directory解决方案确保正确设置包含路径。ENet头文件在include/enet/目录中应该使用#include enet/enet.h而不是#include enet.h。2. 链接错误未定义的网络函数解决方案在Linux/macOS上链接-lenet在Windows上还需要链接Winsock库# Linux/macOS gcc program.c -lenet -o program # Windows (MinGW) gcc program.c -lenet -lws2_32 -o program.exe # Windows (Visual Studio) # 在项目属性中添加enet.lib和ws2_32.lib3. 性能问题延迟过高解决方案检查是否过度使用可靠传输考虑使用多个通道分离不同类型的数据调整缓冲区大小和超时设置使用enet_host_service()的适当超时值避免忙等待4. 内存泄漏检测ENet提供了完善的内存管理但如果你怀疑有内存泄漏可以启用调试模式// 在初始化前设置回调函数 ENetCallbacks callbacks; callbacks.malloc my_malloc; callbacks.free my_free; callbacks.no_memory my_no_memory; enet_initialize_with_callbacks(ENET_VERSION, callbacks);进阶技巧打造专业级网络系统当你掌握了ENet的基础后可以尝试这些进阶技巧1. 自定义协议扩展ENet的协议设计非常灵活。你可以查看protocol.c和protocol.h了解内部协议细节甚至可以扩展它来满足特定需求。2. 加密与安全虽然ENet本身不提供加密功能但你可以轻松添加// 发送前加密 void encrypt_packet(ENetPacket* packet) { // 实现你的加密逻辑 } // 接收后解密 void decrypt_packet(ENetPacket* packet) { // 实现你的解密逻辑 }3. 流量统计与监控ENet提供了丰富的统计信息// 获取主机统计信息 printf(总发送数据: %u bytes\n, host-totalSentData); printf(总接收数据: %u bytes\n, host-totalReceivedData); printf(总发送包数: %u\n, host-totalSentPackets); printf(总接收包数: %u\n, host-totalReceivedPackets); // 获取对等体统计信息 printf(往返时间: %u ms\n, peer-roundTripTime); printf(丢包率: %u%%\n, peer-packetLoss);4. 异步IO集成对于高性能服务器可以考虑将ENet与异步IO框架如libevent、libuv集成实现更高的并发性能。下一步行动从入门到精通恭喜你现在你已经掌握了ENet可靠UDP网络库的核心知识。但学习之旅才刚刚开始这里有一些建议帮助你继续深入阅读官方文档查看docs/目录中的设计文档特别是design.dox和tutorial.dox里面有丰富的技术细节和最佳实践。研究源码ENet的源码非常清晰是学习网络编程的绝佳材料。特别关注protocol.c中的协议实现和host.c中的主机管理逻辑。加入社区虽然ENet项目本身活跃度不高但有很多使用ENet的开源项目。研究这些项目可以学到很多实战经验。动手实践最好的学习方式就是动手。尝试用ENet构建一个小型多人游戏、聊天系统或实时数据同步应用。性能测试搭建测试环境对比ENet与原生TCP/UDP的性能差异了解在不同场景下的表现。ENet可靠UDP网络库是一个经过时间考验的优秀网络库它简洁、高效、可靠。无论你是游戏开发者、实时应用工程师还是对网络编程感兴趣的学习者ENet都能为你提供强大的支持。记住网络编程的核心是理解数据如何在网络中流动。ENet为你处理了底层的复杂性让你可以专注于业务逻辑的实现。现在开始你的ENet之旅吧用这个强大的工具构建出色的网络应用温馨提示在实际项目中记得充分测试网络异常情况如断线重连、网络抖动、高延迟环境等。ENet虽然强大但没有任何网络库能替代良好的错误处理和用户体验设计。祝你在网络编程的道路上越走越远用ENet构建出令人惊艳的实时应用【免费下载链接】enetENet reliable UDP networking library项目地址: https://gitcode.com/gh_mirrors/en/enet创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

如何快速部署Sentora Core:从安装到配置的完整教程

如何快速部署Sentora Core:从安装到配置的完整教程

2026/8/10 19:27:27

如何快速部署Sentora Core:从安装到配置的完整教程 【免费下载链接】sentora-core Sentora is a web hosting control panel written in PHP for *NIX 项目地址: https://gitcode.com/gh_mirrors/se/sentora-core Sentora Core是一款基于PHP开发的开源Web托管…

iOS开发 Swift 速记6:枚举(超复杂)

iOS开发 Swift 速记6:枚举(超复杂)

2026/8/10 19:27:27

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的,可以在任何平台上使用。 源码指引:github源…

iOS开发 Swift 速记7:结构体和类

iOS开发 Swift 速记7:结构体和类

2026/8/10 19:27:27

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的,可以在任何平台上使用。 源码指引:github源…

Livox激光雷达SDK2完整指南:5分钟快速上手开发教程

Livox激光雷达SDK2完整指南:5分钟快速上手开发教程

2026/8/10 22:57:38

Livox激光雷达SDK2完整指南:5分钟快速上手开发教程 【免费下载链接】Livox-SDK2 Drivers for receiving LiDAR data and controlling lidar, support Lidar HAP and Mid-360. 项目地址: https://gitcode.com/gh_mirrors/li/Livox-SDK2 Livox激光雷达SDK2是专…

如何永久保存微信聊天记录:WeChatMsg完整指南,轻松掌握数据主权

如何永久保存微信聊天记录:WeChatMsg完整指南,轻松掌握数据主权

2026/8/10 22:57:38

如何永久保存微信聊天记录:WeChatMsg完整指南,轻松掌握数据主权 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitH…

断裂力学与多物理场耦合模型解析

断裂力学与多物理场耦合模型解析

2026/8/10 22:57:38

1. 断裂力学与多物理场耦合模型概述 断裂力学作为固体力学的重要分支,研究含裂纹结构在外载荷作用下的力学行为。当我们将断裂力学与多物理场耦合模型相结合时,就打开了一个全新的研究维度。这种交叉研究不仅考虑了力学因素,还纳入了热、电、…

终极免费波表合成器Vital:光谱变形技术如何重塑声音设计体验

终极免费波表合成器Vital:光谱变形技术如何重塑声音设计体验

2026/8/10 22:57:38

终极免费波表合成器Vital:光谱变形技术如何重塑声音设计体验 【免费下载链接】vital Spectral warping wavetable synth 项目地址: https://gitcode.com/gh_mirrors/vi/vital Vital是一款革命性的开源波表合成器,采用创新的光谱变形技术&#xff…

Unity贪吃蛇游戏开发全流程:从核心逻辑到打包发布

Unity贪吃蛇游戏开发全流程:从核心逻辑到打包发布

2026/8/10 22:57:38

1. 项目概述:从一份源码到可玩程序的完整旅程最近在整理硬盘时,翻出了一个几年前用Unity做的贪吃蛇小游戏项目。这个项目麻雀虽小,但五脏俱全,包含了从游戏逻辑、UI交互到最终打包成可执行程序(exe)的完整流…

3步构建大麦自动抢票系统:告别手动抢票的终极指南

3步构建大麦自动抢票系统:告别手动抢票的终极指南

2026/8/10 22:47:38

3步构建大麦自动抢票系统:告别手动抢票的终极指南 【免费下载链接】ticket-purchase 大麦自动抢票,支持人员、城市、日期场次、价格选择 项目地址: https://gitcode.com/GitHub_Trending/ti/ticket-purchase 还在为抢不到演唱会门票而烦恼吗&…

比较好的亚太EMBA,问了6位校友师资差别真的挺大

比较好的亚太EMBA,问了6位校友师资差别真的挺大

2026/8/10 5:58:32

比较好的亚太EMBA核心差异先看什么?对于希望兼顾工作与系统管理能力提升的亚太区高管而言,筛选匹配度高的EMBA项目时,师资配置是决定学习体验与实际收获的核心要素之一。我们结合3-4个公开信息透明、办学历史较长的亚太区主流EMBA项目特点&am…

备考3个月对比6份资料 海外游学的亚洲EMBA面试注意点

备考3个月对比6份资料 海外游学的亚洲EMBA面试注意点

2026/8/10 7:54:12

备考海外游学的亚洲EMBA面试,核心要围绕项目国际化设计逻辑、个人跨文化管理经验匹配度两个维度准备,避免把游学模块等同于普通旅游参访的认知偏差。不少备考者花3个月对比6份资料,却容易忽略面试官对“国际视野落地能力”的考察——比如香港…

比较好的国内EMBA,问了二十位校友聊透人脉价值

比较好的国内EMBA,问了二十位校友聊透人脉价值

2026/8/10 7:19:21

比较好的国内EMBA核心差异体现在哪些方面?比较好的国内EMBA的核心长期价值,很大程度上依托于校友网络的连接质量与资源生态的活跃度,这也是不少高管在择校时优先考量的因素。我们结合3-4个市场关注度较高的项目公开信息,从课程、师…

Prometheus 监控体系深度部署:选型别只看功能清单

Prometheus 监控体系深度部署:选型别只看功能清单

2026/8/10 0:06:33

Prometheus 监控体系深度部署:选型别只看功能清单 选型场景:小规模集群直接部署 Thanos 的代价 如果为解决 15 天本地存储限制,直接部署 Thanos Sidecar、Store Gateway、Querier、Compactor、Ruler、Bucket Web 并接入 S3,就需…

ELK 日志分析平台与全链路追踪:代码评审该盯住哪些细节

ELK 日志分析平台与全链路追踪:代码评审该盯住哪些细节

2026/8/10 0:06:33

ELK 日志分析平台与全链路追踪:代码评审该盯住哪些细节 场景示例:一条 2MB 日志影响 Elasticsearch 写入 一个上传接口若执行 log.Info("Request dumped: ", r.Body),会将 2MB 的二进制 Body 写入日志。高并发下,这类超…

从零到一构建开源项目的完整历程:代码评审该盯住哪些细节

从零到一构建开源项目的完整历程:代码评审该盯住哪些细节

2026/8/10 0:06:33

从零到一构建开源项目的完整历程:代码评审该盯住哪些细节 项目进入稳定版本后,外部 Pull Request(PR)会带来新的协作成本。大范围改动混入风格重构,或修复局部问题时修改公共函数签名,都可能扩大评审和兼容…

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

2026/8/8 5:07:31

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…

导师推荐!2026最新AI论文工具测评与实用推荐

导师推荐!2026最新AI论文工具测评与实用推荐

2026/8/9 13:42:46

2026年真正好用的AI论文工具,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

告别游戏崩溃:XCOM 2模组管理器的智能革命

告别游戏崩溃:XCOM 2模组管理器的智能革命

2026/8/8 2:30:15

告别游戏崩溃:XCOM 2模组管理器的智能革命 【免费下载链接】xcom2-launcher The Alternative Mod Launcher (AML) is a replacement for the default game launchers from XCOM 2 and XCOM Chimera Squad. 项目地址: https://gitcode.com/gh_mirrors/xc/xcom2-lau…