# Ping ***Copyright © Quectel Wireless Solutions Co., Ltd. 2026. All rights reserved.*** --- # 功能概述 Ping是一种基于ICMP(Internet Control Message Protocol,互联网控制报文协议)的网络诊断工具,主要用于测试主机间的网络连通性、测量RTT(Round-Trip Time,往返时间)和评估丢包率。 - 核心机制:发送ICMP Echo_Request,等待目标主机返回ICMP Echo_Reply。 - 在嵌入式/物联网场景中,Ping的常见用途包括: - 开机自检 - 周期性心跳 - 故障定位(DNS、路由、防火墙) ## 基本要素 1. **工作原理**:基于ICMP协议的回显请求/应答机制实现连通性检测:模块发送Echo包到目标主机;若目标主机存活且网络可达,将返回Echo-Reply包,以此验证双向连通性。 2. **网络协议支持**:Ping功能的实现依赖于底层网络协议栈对ICMP协议的完整支持。 3. **网络接口配置**:系统需正确配置网络接口参数(如IP地址、子网掩码和默认网关等),以确保网络数据包的正常收发。 4. **高精度定时器**:为准确测量RTT,嵌入式系统需提供高精度的硬件或软件定时器来计算时间差。 5. **TTL(Time To Live,生存时间)**:控制数据包在网络中的最大路由跳数。每经过一个路由器,TTL值减1;当TTL递减至0时,数据包将被丢弃并返回ICMP Time Exceeded消息。 6. **输入参数**: - 目标地址:目标主机的域名或IPv4/IPv6地址。 - 字节数:ICMP数据报文的字节数。 - 次数:单次Ping操作中发送Echo报文的次数。 - 时间:等待Echo Reply报文的最大时间阈值(毫秒)。 - TTL:Echo报文在网络中的最大转发跳数。 7. **输出结果**: - 字节数:接收到的应答报文大小。 - TTL:应答报文的剩余生存时间。 - RTT:从发送请求到接收应答的时间差。 - 远程IP地址:应答报文的源IP地址。 - 最终统计信息:包括发送包数,接收包数、丢包数、最小RTT,最大RTT,平均RTT等。 8. **常见结果**: - 成功连接:正常接收到Reply报文。 - 主机不存在:显示“请求找不到主机”。 - 请求超时:Echo报文到达目标但Reply报文丢失。 - 无法访问目标主机:Echo报文在传输途中被终止。 9. **故障排查步骤**: - *Ping 127.0.0.1*:验证本地TCP/IP协议栈是否正常。 - *Ping [本机IP]*:验证本地网卡及网络接口配置。 - *Ping [网关IP]*:检查网络连接。 - *Ping [远端主机IP]*:测试与外部网络的连通性。 ## 流程概述 1. **创建数据包**:源主机创建一个包含ICMP报文的数据包。默认报文长度为56字节,报文中包含数据包标识符(通常为进程ID)、序列号和时间戳等信息。 2. **发送数据包**:将创建的数据包通过本地网络接口发送至目标主机,进入网络传输链路。 3. **接收响应**:目标主机接收到数据包后,若网络连接畅通,将构造并返回一个ICMP Echo Reply(回送应答)报文。该报文的标识符与序列号必须与原始请求报文保持一致。 4. **解析结果**:源主机接收到目标主机的回送应答报文后,匹配标识符与序列号完成报文配对,并根据时间戳计算RTT,随后输出诊断结果。 5. **循环执行**:根据设置的数据包发送次数,循环执行上述收发过程,达到指定次数后停止。 ## ICMP报文标准结构 ### Ping请求包(ICMP ECHO_REQUEST)结构 [IP头部][ICMP类型=8][ICMP代码=0][校验和][标识符][序列号][数据(时间戳+填充)] 1. **IP头部**(20字节) - 包含源IP地址、目的IP地址、TTL等字段。 2. **ICMP头部**(8字节) - **ICMP类型(Type)**:8(回显请求ECHO_REQUEST)。 - **ICMP代码(Code)**:0。 - **校验和(Checksum)**:用于验证ICMP头部和数据的完整性。 - **标识符(Identifier)**:用于匹配请求与响应报文。 - **序列号(Sequence Number)**:用于匹配请求和响应报文。 3. **数据部分** - 默认为56字节,可配置。 - 通常包含用于计算RTT的时间戳信息和用于填充的固定字符串(如"ping")。 ### Ping应答包(ICMP ECHO_REPLY)结构 [IP头部][ICMP类型=0][ICMP代码=0][校验和][标识符][序列号][数据(与请求包相同)] 1. **IP头部**(20字节) - 包含源IP地址(原始目的IP)、目的IP地址(原始源IP)、TTL等字段。 2. **ICMP头部**(8字节) - **ICMP类型(Type)**:0(回显应答ECHO_REPLY)。 - **ICMP代码(Code)**:0。 - **校验和(Checksum)**:重新计算以匹配回应包。 - **标识符(Identifier)**:与请求包相同,用于报文配对。 - **序列号(Sequence Number)**:与请求包相同,用于报文配对。 3. **数据部分**: - 与请求包的数据部分完全相同(包括时间戳和填充字节)。 ### 补充说明 - **TTL字段**:请求包的TTL通常设置为255,远端应答包的TTL取决于目标主机的操作系统(如BSD系统常设置为255,其他系统可能设置为30或60)。 - **校验和计算**:ICMP头部和数据的校验和是整个ICMP消息(包括头部和数据)的16位补码和。 以下是Ping请求包和应答包的消息结构: ```{image} images/image_NNTwbC6QzoRfwmxQ616crxCrnPc.webp :width: 1901px :height: 900px :align: center ``` # Ping API ## 头文件 *qcm_ping_app.h* ## 函数概览 | **函数** | **描述** | | --- | --- | | *qcm_ping_start()* | 启用Ping功能并根据配置信息设置发送的数据包 | ## 函数详解 ### qcm_ping_start - **功能描述** 启用Ping功能并根据配置信息设置发送的数据包。 - **函数原型** ```c qcm_ping_error_e qcm_ping_start(qosa_int32_t cid, qosa_int32_t sim_id, const char *host, qcm_ping_config_type *ping_options, qcm_ping_event_cb cb_fun, void *user_param); ``` - **参数说明** | **参数名** | **输入/输出** | **类型** | **说明** | | --- | --- | --- | --- | | *cid* | 输入 | qosa_int32_t | PDP Client ID | | *sim_id* | 输入 | qosa_int32_t | SIM ID
*0*:SIM卡1
*1*:SIM卡2 | | *host* | 输入 | const char * | 目标主机的域名或IPv4/IPv6地址 | | *ping_options* | 输入 | *qcm_ping_config_type \** | Ping的配置信息;详见 [*qcm_ping_config_type*](#qcmpingconfig_type) | | *cb_fun* | 输入 | *qcm_ping_event_cb* | Ping事件的回调函数;详见 [*qcm_ping_event_cb*](#qcmpingevent_cb) | | *user_param* | 输入 | void* | 用户自定义参数 | - **返回值说明** *QCM_PING_OK*:函数执行成功 其他值:函数执行失败;详见 [*qcm_ping_error_e*](#qcmpingerror_e) #### qcm_ping_event_cb - **函数原型** ```c typedef void (*qcm_ping_event_cb)(qcm_ping_event_type event_id, qcm_ping_error_e evt_code, qcm_ping_resp_t *resp_ptr, void *user_param); ``` - **参数说明** | **参数名** | **输入/输出** | **类型** | **说明** | | --- | --- | --- | --- | | *event_id* | 输入 | *qcm_ping_event_type* | Ping返回的事件类型;详见 [*qcm_ping_event_type*](#qcmpingevent_type) | | *evt_code* | 输入 | *qcm_ping_error_e* | Ping事件的结果码;详见 [*qcm_ping_error_e*](#qcmpingerror_e) | | *resp_ptr* | 输入 | *qcm_ping_resp_t \** | Ping返回的响应信息;详见 [*qcm_ping_resp_t*](#qcmpingresp_t) | | *user_param* | 输入 | void* | 用户自定义参数 | - **返回值说明** 无 ## 结构体定义 ### qcm_ping_config_type Ping的配置信息结构体定义如下: ```c typedef struct { qosa_uint32_t num_data_bytes; qosa_uint32_t ping_response_time_out; qosa_uint32_t num_pings; qosa_uint32_t ttl; } qcm_ping_config_type; ``` | **参数** | **类型** | **说明** | | --- | --- | --- | | *num_data_bytes* | qosa_uint32_t | Ping数据包大小;单位:字节 | | *ping_response_time_out* | qosa_uint32_t | 等待PING响应的超时时间;单位:毫秒 | | *num_pings* | qosa_uint32_t | Ping的次数 | | *ttl* | qosa_uint32_t | Ping数据包的TTL | ### qcm_ping_resp_t Ping返回的响应信息结构体定义如下: ```c typedef struct { union { qcm_ping_summary_type summary; qcm_ping_stats_type status; } type; } qcm_ping_resp_t; ``` | **参数** | **类型** | **说明** | | --- | --- | --- | | summary | *qcm_ping_summary_type* | Ping的汇总统计信息;详见 [*qcm_ping_summary_type*](#qcmpingsummary_type) | | status | *qcm_ping_stats_type* | Ping的实时状态信息;详见 [*qcm_ping_stats_type*](#qcmpingstats_type) | ### qcm_ping_summary_type Ping的汇总统计信息结构体定义如下: ```c typedef struct { qosa_uint32_t min_rtt; qosa_uint32_t max_rtt; qosa_uint32_t avg_rtt; qosa_uint32_t num_pkts_sent; qosa_uint32_t num_pkts_recvd; qosa_uint32_t num_pkts_lost; } qcm_ping_summary_type; ``` | **参数** | **类型** | **说明** | | --- | --- | --- | | *min_rtt* | qosa_uint32_t | RTT的最小值;单位:毫秒 | | *max_rtt* | qosa_uint32_t | RTT的最大值;单位:毫秒 | | *avg_rtt* | qosa_uint32_t | RTT的平均值;单位:毫秒 | | *num_pkts_sent* | qosa_uint32_t | 已发送数据包数量 | | *num_pkts_recvd* | qosa_uint32_t | 已接收回应包数量 | | *num_pkts_lost* | qosa_uint32_t | 丢失的数据包数量 | ### qcm_ping_stats_type Ping的实时状态信息结构体定义如下: ```c typedef struct { qosa_uint32_t ping_rtt; qosa_uint32_t ping_size; qosa_uint32_t ping_ttl; char resolved_ip_addr[CONFIG_QOSA_INET6_ADDRSTRLEN]; } qcm_ping_stats_type; ``` | **参数** | **类型** | **说明** | | --- | --- | --- | | *ping_rtt* | qosa_uint32_t | RTT值 | | *ping_size* | qosa_uint32_t | Ping数据包的大小;单位:字节 | | *ping_ttl* | qosa_uint32_t | Ping数据包的TTL值 | | *resolved_ip_addr* | char | Ping目标主机IP地址 | ## 枚举定义 ### qcm_ping_event_type Ping返回的事件类型枚举定义如下: ```c typedef enum { QCM_PING_STATS = 1, QCM_PING_SUMMARY = 2, } qcm_ping_event_type; ``` | **成员** | **说明** | | --- | --- | | *QCM_PING_STATS* | 单次的Ping结果 | | *QCM_PING_SUMMARY* | Ping的统计信息 | ### qcm_ping_error_e Ping事件的结果码枚举定义如下: ```c typedef enum { QCM_PING_OK = 0, QCM_PING_SEND_END = 1, QCM_PING_ERR_UNKNOW = (QOSA_COMPONENT_PING << 16) | 550, QCM_PING_ERR_INVALID_PARAM = (QOSA_COMPONENT_PING << 16) | 552, QCM_PING_ERR_MEMORY = (QOSA_COMPONENT_PING << 16) | 553, QCM_PING_ERR_SOCKET_NEW_FAILURE = (QOSA_COMPONENT_PING << 16) | 554, QCM_PING_ERR_SOCKET_BIND_FAILURE = (QOSA_COMPONENT_PING << 16) | 556, QCM_PING_ERR_SOCKET_WRITE_FAILURE = (QOSA_COMPONENT_PING << 16) | 558, QCM_PING_ERR_SOCKET_READ_FAILURE = (QOSA_COMPONENT_PING << 16) | 559, QCM_PING_ERR_PDP_ACTIVE_FAILURE = (QOSA_COMPONENT_PING << 16) | 561, QCM_PING_ERR_DNS_FAILURE = (QOSA_COMPONENT_PING << 16) | 565, QCM_PING_ERR_SOCKET_CONNECT_FAILURE = (QOSA_COMPONENT_PING << 16) | 566, QCM_PING_ERR_TIMEOUT = (QOSA_COMPONENT_PING << 16) | 569, QCM_PING_ERR_OPERATION_NOT_ALLOWED = (QOSA_COMPONENT_PING << 16) | 572, } qcm_ping_error_e; ``` | **成员** | **说明** | | --- | --- | | *QCM_PING_OK* | 函数执行成功 | | *QCM_PING_SEND_END* | 数据包发送结束 | | *QCM_PING_ERR_UNKNOW* | 未知错误 | | *QCM_PING_ERR_INVALID_PARAM* | 参数无效 | | *QCM_PING_ERR_MEMORY* | 内存不足 | | *QCM_PING_ERR_SOCKET_NEW_FAILURE* | 创建Socket失败 | | *QCM_PING_ERR_SOCKET_BIND_FAILURE* | Socket绑定失败 | | *QCM_PING_ERR_SOCKET_WRITE_FAILURE* | Socket写入失败 | | *QCM_PING_ERR_SOCKET_READ_FAILURE* | Socket读取失败 | | *QCM_PING_ERR_PDP_ACTIVE_FAILURE* | PDP上下文激活失败 | | *QCM_PING_ERR_DNS_FAILURE* | DNS解析失败 | | *QCM_PING_ERR_SOCKET_CONNECT_FAILURE* | Socket连接失败 | | *QCM_PING_ERR_TIMEOUT* | 操作超时 | | *QCM_PING_ERR_OPERATION_NOT_ALLOWED* | 操作不允许 | # 应用逻辑流程图 ```{image} images/board_FhLEwJMojh0B6Mb7ZDpcP50yn4b.jpg :width: 787px :height: 801px :align: center ``` # 示例代码 完整示例代码请查看 https://github.com/UniRTOS/UniRTOS-Doc-Examples/blob/main/network/network_protocol/ping/ping_demo.c # Ping功能配置建议 | **参数** | **推荐值** | **说明** | | --- | --- | --- | | *num_data_bytes* | 32~1472 | 过大的载荷可能导致数据包超出网络MTU限制,从而引发分片或丢弃 | | *num_pings* | 4~10 | 平衡测试耗时与统计结果准确性 | | *ping_response_time_out* | 1000~5000 | 2000毫秒适用于大多数网络情景 | | *ttl* | 32~255 | 64适用于大多数网络情景 | # 常见问题排查指南 | **错误码/问题)** | **可能原因** | **建议解决方案** | | --- | --- | --- | | *QCM_PING_ERR_INVALID_PARAM*(参数无效) | 输入参数为空、参数设置超出范围或格式错误 | | | *QCM_PING_ERR_MEMORY*(内存不足) | 系统内存分配失败,任务栈空间过小或堆内存耗尽 | | | *QCM_PING_ERR_SOCKET_NEW_FAILURE*(创建Socket失败) | 网络栈未初始化或Socket资源耗尽 | | | *QCM_PING_ERR_SOCKET_BIND_FAILURE*(Socket绑定失败) | 本地IP配置异常、端口冲突或系统权限/防火墙拦截 | | | *QCM_PING_ERR_SOCKET_WRITE_FAILURE*(Socket写入失败) | 网络连接中断或缓冲区满 | | | *QCM_PING_ERR_SOCKET_READ_FAILURE*(Socket读取失败) | 响应包丢失或读取超时 | | | *QCM_PING_ERR_PDP_ACTIVE_FAILURE*(PDP上下文激活失败) | SIM卡未就绪、网络未注册或APN配置错误 | | | *QCM_PING_ERR_DNS_FAILURE*(DNS解析失败) | 域名无效、网络无DNS服务器或解析超时 | | | *QCM_PING_ERR_SOCKET_CONNECT_FAILURE*(Socket连接失败) | 目标不可达、防火墙阻挡或路由问题 | | | *QCM_PING_ERR_TIMEOUT*(操作超时) | 响应超时时间过短或网络延迟高 | | | *QCM_PING_ERR_OPERATION_NOT_ALLOWED*(操作不允许) | 权限不足或模块未启用Ping功能 | | | *QCM_PING_ERR_UNKNOW*(未知错误) | 未分类错误,可能为底层系统问题 | - | | 无错误但RTT高、丢包率高 | 网络拥塞、信号弱或目标服务器负载 | | | 回调未触发(无 *QCM_PING_STATS*/*SUMMARY*) | 任务/消息队列未正确初始化或阻塞 | |