PingForAndroid
C庫採用SOCK_DGRAM方式構建icmp包,避開raw socket必須root權限的限制,實現ping功能。
Github: https://github.com/bgylde/PingForAndroid
ping實現方式
1. 通常實現方式
這種方式是直接創建網絡層的socket,可以自己構建ip包,也可以委託系統填充。好處是返回的數據包也包括ip數據包,可以獲取ttl數據,但是創建raw socket需要擁有root權限這也限制了不能在android上面採用。
socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
2. 避過root權限限制解決方案
這種方式採用DGRAM方式創建socket,不會被root權限所限制,缺點是返回的數據包不包含ip包數據,無法獲取ttl數據。經過測試可以在Android平臺通過jni使用,可以滿足基本需求。
socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
採用這種方式利用了ICMP協議的特性,數據部分不會被修改,會原樣返回,所以可以填充發送時間和自己計算首部的校驗和來驗證自己發送的包;
typedef struct _TAG_ICMP_PACKET
{
ICMP_HEADER icmp_header; //icmp頭部,需要根據icmp協議構建
struct timeval icmp_time; //自己填充發送時間,用於計算往返時間
u_int16_t icmp_sum_flag; //自己填充校驗和,驗證是否是自己發送的ICMP包
u_int8_t imcp_data[DATA_SIZE]; //其它數據,直接填充0
} ICMP_PACKET;
經過驗證,在mac上面還是可以收到ip首部,移植到android平臺就不會收到ip頭的數據;所以還是添加了對ip首部的處理邏輯,自己的校驗和也添加上,可以在mac平臺正常使用。
如果對您有用的話麻煩star支持一下~非常感謝