# 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*(参数无效) | 输入参数为空、参数设置超出范围或格式错误 |