HarmonyOS 鸿蒙Next网络诊断需要使用ping命令

发布于 1周前 作者 wuwangju 来自 鸿蒙OS

HarmonyOS 鸿蒙Next网络诊断需要使用ping命令

app提供了网络诊断的功能,其中包括ping一些指定的host是否成功,,有没有相应的api,或者推荐哪种实现方案 

2 回复

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命令的基本步骤:

  1. 打开终端应用:在鸿蒙设备上找到并打开终端(Terminal)应用,该应用通常预装在鸿蒙系统的开发工具或特定设备中。

  2. 输入ping命令:在终端中输入ping命令后接目标IP地址或域名。例如,要ping一个IP地址为192.168.1.1的设备,输入ping 192.168.1.1;若要ping一个域名,如www.example.com,则输入ping www.example.com

  3. 查看输出结果:命令执行后,终端会显示一系列数据包发送和接收的信息,包括每个数据包的往返时间(RTT)。如果目标主机可达,你会看到类似“64 bytes from xxx.xxx.xxx.xxx: icmp_seq=1 ttl=64 time=x.xx ms”的响应。

  4. 停止ping操作:默认情况下,ping命令会持续发送数据包直到手动停止。你可以通过按Ctrl+C组合键来中断ping操作。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html。

回到顶部