HarmonyOS 鸿蒙Next网络诊断需要使用ping命令
HarmonyOS 鸿蒙Next网络诊断需要使用ping命令
ArkTS代码目前不支持ping命令,可以通过C代码实现ping命令,封装之后供ArkTS调用
步骤:
1、以模块名为 pingUtil 为例,新增模块:New——Module——种类选择Native C,名字pingUtil
2、在pingUtil 模块 src——main——cpp 文件夹内新增 ping.cpp 文件,粘贴下列代码进去
#include “ping.h”
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
#include <errno.h>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include “hilog/log.h”
#include <netdb.h>
#include <netinet/ip6.h>
#include <netinet/icmp6.h>
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<signal.h>
#include<arpa/inet.h>
#include<sys/time.h>
#include<string.h>
#include<netdb.h>
#include <pthread.h>
#define MAGIC “1234567890”
#define MAGIC_LEN 11
#define IP_BUFFER_SIZE 65536
#define RECV_TIMEOUT_USEC 100000
using namespace std;
#define PACK_SIZE 4096
//使用的结构声明
char *recv_packet; //接收报文结构
int sockfd; //套接字
pid_t pid; //进程号
int timebegin=0; //记录发收的包的数量
int timeend = 0;
int datalen=56; //icmp数据长度,注意完成数据报文最小为64bytes,不是56bytes
struct timeval recv_time; //记录某一刻的时间
struct sockaddr_in from;
struct attribute((packed)) icmp_echo {
// header
uint8_t type;
uint8_t code;
uint16_t checksum;
uint16_t ident;
uint16_t seq;
// data
double sending_ts;
char magic[MAGIC_LEN];
};
double TestPing::get_timestamp() {
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec + ((double)tv.tv_usec) / 1000000;
}
unsigned short TestPing::calculate_checksum(unsigned char *buffer, int bytes) {
uint32_t checksum = 0;
unsigned char *end = buffer + bytes;
// odd bytes add last byte and reset end
if (bytes % 2 == 1) {
end = buffer + bytes - 1;
checksum += (*end) << 8;
}
// add words of two bytes, one by one
while (buffer < end) {
checksum += (buffer[0] << 8) + buffer[1];
// add carry if any
uint32_t carray = checksum >> 16;
if (carray != 0) {
checksum = (checksum & 0xffff) + carray;
}
buffer += 2;
}
// negate it
checksum = ~checksum;
return checksum & 0xffff;
}
int TestPing::send_echo_request(int sock, struct sockaddr_in *addr, int ident, int seq) {
struct icmp_echo icmp;
bzero(&icmp, sizeof(icmp));
// fill header files
icmp.type = 8;
icmp.code = 0;
icmp.ident = htons(ident);
icmp.seq = htons(seq);
// fill magic string
strncpy(icmp.magic, MAGIC, MAGIC_LEN);
// fill sending timestamp
icmp.sending_ts = get_timestamp();
// calculate and fill checksum
icmp.checksum = htons(calculate_checksum((unsigned char *)&icmp, sizeof(icmp)));
// send it
int bytes = sendto(sock, &icmp, sizeof(icmp), 0, (struct sockaddr *)addr, sizeof(*addr));
if (bytes == -1) {
return -1;
}
return 0;
}
std::string TestPing::recv_echo_reply(int sock, int ident) {
// allocate buffer
OH_LOG_DEBUG(LOG_APP, “Start recv_echo_reply”);
unsigned char buffer[IP_BUFFER_SIZE];
struct sockaddr_in peer_addr;
// receive another packet
socklen_t addr_len = sizeof(peer_addr);
int bytes = recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr *)&peer_addr, &addr_len);
if (bytes == -1) {
// normal return when timeout
if (errno == EAGAIN || errno == EWOULDBLOCK) {
printf(“timeout\n”);
OH_LOG_DEBUG(LOG_APP, “errno == EAGAIN || errno == EWOULDBLOCK, timeout, return\n”);
return “”;
}
printf(“recvfrom bytes is -1\n”);
OH_LOG_DEBUG(LOG_APP, “recvfrom bytes is -1, return\n”);
return “”;
}
int ip_header_len = (buffer[0] & 0xf) << 2;
// find icmp packet in ip packet
struct icmp_echo *icmp = (struct icmp_echo *)(buffer + ip_header_len);
// check type
if (icmp->type != 0 || icmp->code != 0) {
printf(“check type failed\n”);
OH_LOG_DEBUG(LOG_APP, “check type failed\n”);
return “”;
}
struct ip *iphdr = (struct ip *)buffer; // IP头部
std::ostringstream stream;
stream << inet_ntoa(peer_addr.sin_addr) << " seq=" << ntohs(icmp->seq)
<< " ttl=" << static_cast<unsigned int>(iphdr->ip_ttl) << " time=" << std::fixed << std::setprecision(2)
<< (get_timestamp() - icmp->sending_ts) * 1000 << “ms\n”;
OH_LOG_DEBUG(LOG_APP, “stream.str(): %s\n”, stream.str().c_str());
std::cout << stream.str() << std::endl;
return stream.str();
}
std::string TestPing::ping(const char *ip) {
OH_LOG_DEBUG(LOG_APP, “Start ping”);
// for store destination address
struct sockaddr_in addr;
bzero(&addr, sizeof(addr));
// fill address, set port to 0
addr.sin_family = AF_INET;
addr.sin_port = 0;
if (inet_aton(ip, (struct in_addr *)&addr.sin_addr.s_addr) == 0) {
OH_LOG_DEBUG(LOG_APP, “bad ip address: %s\n”, ip);
struct hostent* hptr = gethostbyname(ip);
memcpy(&addr.sin_addr,hptr->h_addr,sizeof(hptr->h_addr));
}
// create raw socket for icmp protocol
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
if (sock == -1) {
OH_LOG_DEBUG(LOG_APP, “create icmp socket error”);
return “create icmp socket error”;
}
// set socket timeout option
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = RECV_TIMEOUT_USEC;
int ret = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
if (ret == -1) {
OH_LOG_DEBUG(LOG_APP, “setsockopt option error”);
return “setsockopt option error”;
}
double next_ts = get_timestamp();
int ident = getpid();
int seq = 1;
// time to send another packet
double current_ts = get_timestamp();
if (current_ts >= next_ts) {
// send it
ret = send_echo_request(sock, &addr, ident, seq);
if (ret == -1) {
perror(“Send failed”);
OH_LOG_DEBUG(LOG_APP, “Send failed”);
return “Send failed”;
}
// update next sendint timestamp to one second later
next_ts = current_ts + 1;
// increase sequence number
seq += 1;
}
// try to receive and print reply
std::string recv_ping_echo_reply = recv_echo_reply(sock, ident);
if (recv_ping_echo_reply == “”) {
perror(“Receive failed”);
OH_LOG_DEBUG(LOG_APP, “Receive failed”);
return “Receive failed”;
}
return recv_ping_echo_reply;
}
3、在pingUtil 模块 src——main——cpp 文件夹内新增头文件 ping.h 文件,粘贴下列代码进去
#ifndef PING_PING_H
#define PING_PING_H
#include <string>
class TestPing {
public:
std::string ping(const char *ip);
private:
double get_timestamp();
unsigned short calculate_checksum(unsigned char *buffer, int bytes);
int send_echo_request(int sock, struct sockaddr_in *addr, int ident, int seq);
std::string recv_echo_reply(int sock, int ident);
};
#endif //PING_PING_H
4、在napi_init.cpp 文件中新增下列代码
static napi_value Ping(napi_env env, napi_callback_info info) {
OH_LOG_INFO(LOG_APP, “start Ping”);
size_t argc = 1;
napi_value args[1] = {nullptr};
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
int64_t addrValue = 0;
bool flag = false;
napi_get_value_bigint_int64(env, args[0], &addrValue, &flag);
TestPing *a = (TestPing *)addrValue;
char buf[256];
size_t length;
napi_get_value_string_utf8(env, args[0], buf, 256, &length);
napi_value result = nullptr;
std::string resultStr = a->ping(buf);
napi_create_string_utf8(env, resultStr.c_str(), resultStr.length(),&result);
return result;
}
更多关于HarmonyOS 鸿蒙Next网络诊断需要使用ping命令的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙系统中,进行Next网络诊断时,使用ping命令可以帮助你检测网络连接状态及目标主机的可达性。以下是直接在鸿蒙设备上使用ping命令的基本步骤:
-
打开终端应用:在鸿蒙设备上找到并打开终端(Terminal)应用,该应用通常预装在鸿蒙系统的开发工具或特定设备中。
-
输入ping命令:在终端中输入
ping
命令后接目标IP地址或域名。例如,要ping一个IP地址为192.168.1.1的设备,输入ping 192.168.1.1
;若要ping一个域名,如www.example.com
,则输入ping www.example.com
。 -
查看输出结果:命令执行后,终端会显示一系列数据包发送和接收的信息,包括每个数据包的往返时间(RTT)。如果目标主机可达,你会看到类似“64 bytes from xxx.xxx.xxx.xxx: icmp_seq=1 ttl=64 time=x.xx ms”的响应。
-
停止ping操作:默认情况下,ping命令会持续发送数据包直到手动停止。你可以通过按
Ctrl+C
组合键来中断ping操作。
如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html。