inet_ntop(), inet_pton(), htonl(), ntohl()

本文介绍如何使用inet_ntop()和inet_pton()函数进行点分十进制字符串与网络字节序二进制数值的转换,并通过示例展示了这些函数的应用。此外,还介绍了htons()和ntohs()函数在网络字节序与主机字节序之间的转换。

1. inet_ntop()、inet_pton() : 点分十进制字符串(dotted-decimal notation)与网络字节序(network byte order)二进制数值互转

//inet_ntop()函数原型
PCSTR
WSAAPI
inet_ntop(
    _In_                                INT             Family,
    _In_                                PVOID           pAddr,
    _Out_writes_(StringBufSize)         PSTR            pStringBuf,
    _In_                                size_t          StringBufSize
    );
//inet_ntop示例
SOCKADDR_IN addr;
int len = sizeof(SOCKADDR_IN); socket_client = accept(socket_server, (sockaddr*)&addr, &len); char *address = new char; inet_ntop(AF_INET, &(addr.sin_addr.S_un.S_addr), address,sizeof(SOCKADDR_IN));//将网络字节顺序排列的IP转换为字符串IP

 

//inet_pton函数原型
WINSOCK_API_LINKAGE
   INT
   WSAAPI
   inet_pton(
   _In_                                      INT             Family,
   _In_                                      PCSTR           pszAddrString,
   _Out_writes_bytes_(sizeof(IN6_ADDR))      PVOID           pAddrBuf
   );
//inet_pton示例
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(3050);
//addr.sin_addr.S_un.S_addr = inet_addr("192.168.0.101");
int re_inetpton = inet_pton(AF_INET, "192.168.0.101", &(addr.sin_addr.S_un.S_addr));//将点分十进制串转换成网络字节序二进制值,此函数对IPv4地址和IPv6地址都能处理。
if (SOCKET_ERROR == connect(socket_client, (sockaddr*)&addr, sizeof(sockaddr)))
{
    AfxMessageBox(_T("服务器连接失败"));
    return;
}

 

2. htons()、ntohs(): 网络字节序(network byte order)与主机字节序(host byte order)互转

  uint32_t htonl(uint32_t hostlong);  

  uint16_t htons(uint16_t hostshort);  

  uint32_t ntohl(uint32_t netlong);  

  uint16_t ntohs(uint16_t netshort);  

//htons()函数示例
SOCKADDR_IN addr;
memset(&addr, 0, sizeof(SOCKADDR_IN));
addr.sin_port = htons(80);

 

 

 

转载于:https://www.cnblogs.com/zhoudingcocng/p/6209961.html

#define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <net/if.h> #include <netinet/if_ether.h> #include <arpa/inet.h> #include <netpacket/packet.h> #include <sys/ioctl.h> #include <time.h> #include <pthread.h> #include <sys/time.h> // 用户配置结构体 typedef struct { int enable; // 功能开关 (0=禁用, 1=启用) int scan_interval; // 扫描周期 (秒) int entry_timeout; // 条目有效期 (秒) int packet_interval; // 发包间隔 (毫秒) uint32_t start_ip; // 起始IP (网络字节序) uint32_t end_ip; // 结束IP (网络字节序) } UserConfig; // 定义结构体标签 typedef struct ArpEntry { uint32_t ip; // IP地址 (网络字节序) uint8_t mac[6]; // MAC地址 time_t last_seen; // 最后发现时间 struct ArpEntry *next; // 链表指针 (使用结构体标签) } ArpEntry; // 全局变量 UserConfig config = { .enable = 1, // 默认启用 .scan_interval = 60, // 默认60秒 .entry_timeout = 300, // 默认300秒有效期 .packet_interval = 100, // 默认100毫秒发包间隔 .start_ip = 0, // 初始化为0 .end_ip = 0 // 初始化为0 }; ArpEntry *arp_table = NULL; // ARP缓存表头指针 pthread_mutex_t table_mutex = PTHREAD_MUTEX_INITIALIZER; // ARP报文结构 struct arp_packet { struct ethhdr eth_header; struct ether_arp arp_data; }; // 函数声明 void print_config(); void print_arp_table(); void update_arp_entry(uint32_t ip, uint8_t *mac); void cleanup_expired_entries(); void *arp_table_manager(void *arg); // 获取本机MAC地址 void get_mac_address(const char *interface, uint8_t *mac) { int fd = socket(AF_INET, SOCK_DGRAM, 0); struct ifreq ifr; strncpy(ifr.ifr_name, interface, IFNAMSIZ-1); if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) { perror("MAC获取失败"); close(fd); exit(EXIT_FAILURE); } memcpy(mac, ifr.ifr_hwaddr.sa_data, 6); close(fd); } // 获取本机IP地址 void get_ip_address(const char *interface, uint32_t *ip) { int fd = socket(AF_INET, SOCK_DGRAM, 0); struct ifreq ifr; strncpy(ifr.ifr_name, interface, IFNAMSIZ-1); if (ioctl(fd, SIOCGIFADDR, &ifr) == -1) { perror("IP获取失败"); close(fd); exit(EXIT_FAILURE); } *ip = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr; close(fd); } // 创建ARP套接字 int create_arp_socket() { int sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); if (sock < 0) { perror("Socket创建失败"); exit(EXIT_FAILURE); } return sock; } // 发送ARP请求 void send_arp_request(int sock, const char *interface, uint32_t src_ip, uint8_t *src_mac, uint32_t target_ip) { struct arp_packet packet; struct sockaddr_ll addr; // 填充以太网帧头 memset(packet.eth_header.h_dest, 0xFF, ETH_ALEN); // 广播地址 memcpy(packet.eth_header.h_source, src_mac, ETH_ALEN); packet.eth_header.h_proto = htons(ETH_P_ARP); // 填充ARP数据 packet.arp_data.arp_hrd = htons(ARPHRD_ETHER); packet.arp_data.arp_pro = htons(ETH_P_IP); packet.arp_data.arp_hln = ETH_ALEN; packet.arp_data.arp_pln = 4; packet.arp_data.arp_op = htons(ARPOP_REQUEST); memcpy(packet.arp_data.arp_sha, src_mac, ETH_ALEN); memcpy(&packet.arp_data.arp_spa, &src_ip, 4); memset(packet.arp_data.arp_tha, 0x00, ETH_ALEN); // 目标MAC未知 memcpy(&packet.arp_data.arp_tpa, &target_ip, 4); // 配置接口 memset(&addr, 0, sizeof(addr)); addr.sll_family = AF_PACKET; addr.sll_ifindex = if_nametoindex(interface); addr.sll_halen = ETH_ALEN; memcpy(addr.sll_addr, packet.eth_header.h_dest, ETH_ALEN); // 发送数据包 if (sendto(sock, &packet, sizeof(packet), 0, (struct sockaddr*)&addr, sizeof(addr)) < 0) { perror("ARP请求发送失败"); } } // 接收ARP响应 void receive_arp_response(int sock, uint8_t *src_mac) { struct arp_packet recv_packet; struct sockaddr_ll addr; socklen_t addr_len = sizeof(addr); // 设置接收超时 struct timeval tv = {.tv_sec = 1, .tv_usec = 0}; setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); while (1) { ssize_t len = recvfrom(sock, &recv_packet, sizeof(recv_packet), 0, (struct sockaddr*)&addr, &addr_len); if (len < 0) break; // 超时或错误 // 检查是否为ARP响应 if (ntohs(recv_packet.eth_header.h_proto) == ETH_P_ARP && ntohs(recv_packet.arp_data.arp_op) == ARPOP_REPLY) { // 验证发送方MAC是否匹配 if (memcmp(recv_packet.arp_data.arp_tha, src_mac, ETH_ALEN) == 0) { uint32_t resp_ip = *(uint32_t*)recv_packet.arp_data.arp_spa; uint8_t *resp_mac = recv_packet.arp_data.arp_sha; // 检查是否在目标范围内 uint32_t net_resp = ntohl(resp_ip); uint32_t net_start = ntohl(config.start_ip); uint32_t net_end = ntohl(config.end_ip); if (net_resp >= net_start && net_resp <= net_end) { // 更新ARP表 update_arp_entry(resp_ip, resp_mac); } } } } } // 更新ARP条目 void update_arp_entry(uint32_t ip, uint8_t *mac) { pthread_mutex_lock(&table_mutex); ArpEntry *current = arp_table; ArpEntry *prev = NULL; int is_new = 1; time_t now = time(NULL); // 查找是否已存在 while (current != NULL) { if (current->ip == ip) { // 更新现有条目 memcpy(current->mac, mac, 6); current->last_seen = now; is_new = 0; break; } prev = current; current = current->next; } if (is_new) { // 创建新条目 ArpEntry *new_entry = malloc(sizeof(ArpEntry)); new_entry->ip = ip; memcpy(new_entry->mac, mac, 6); new_entry->last_seen = now; new_entry->next = arp_table; arp_table = new_entry; // 打印新主机信息 char ip_str[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &ip, ip_str, INET_ADDRSTRLEN); printf("\n[NEW] Host active: %s [MAC: %02X:%02X:%02X:%02X:%02X:%02X]", ip_str, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); } pthread_mutex_unlock(&table_mutex); } // 清理过期条目 void cleanup_expired_entries() { pthread_mutex_lock(&table_mutex); time_t now = time(NULL); ArpEntry *current = arp_table; ArpEntry *prev = NULL; ArpEntry *next = NULL; while (current != NULL) { next = current->next; // 保存下一个节点 if (difftime(now, current->last_seen) > config.entry_timeout) { // 打印过期信息 char ip_str[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &current->ip, ip_str, INET_ADDRSTRLEN); printf("[EXPIRED] Removing entry: %s\n", ip_str); // 移除条目 if (prev == NULL) { arp_table = next; } else { prev->next = next; } free(current); } else { prev = current; } current = next; // 移动到下一个节点 } pthread_mutex_unlock(&table_mutex); } // ARP表管理线程 void *arp_table_manager(void *arg) { (void)arg; // 避免未使用参数警告 while (1) { sleep(10); // 每10秒检查一次 cleanup_expired_entries(); } return NULL; } // 打印配置信息 void print_config() { char start_ip[INET_ADDRSTRLEN]; char end_ip[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &config.start_ip, start_ip, INET_ADDRSTRLEN); inet_ntop(AF_INET, &config.end_ip, end_ip, INET_ADDRSTRLEN); printf("\n=== 当前配置 ===\n"); printf("功能状态: %s\n", config.enable ? "启用" : "禁用"); printf("扫描周期: %d 秒\n", config.scan_interval); printf("条目有效期: %d 秒\n", config.entry_timeout); printf("发包间隔: %d 毫秒\n", config.packet_interval); printf("起始IP: %s\n", start_ip); printf("结束IP: %s\n", end_ip); printf("================\n"); } // 打印ARP表 void print_arp_table() { pthread_mutex_lock(&table_mutex); ArpEntry *current = arp_table; int count = 0; printf("\n=== ARP表 ===\n"); while (current != NULL) { char ip_str[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &current->ip, ip_str, INET_ADDRSTRLEN); char time_str[20]; struct tm *tm_info = localtime(&current->last_seen); strftime(time_str, 20, "%Y-%m-%d %H:%M:%S", tm_info); printf("%-15s %02X:%02X:%02X:%02X:%02X:%02X 最后发现: %s\n", ip_str, current->mac[0], current->mac[1], current->mac[2], current->mac[3], current->mac[4], current->mac[5], time_str); current = current->next; count++; } printf("总条目: %d\n", count); printf("=======================\n"); pthread_mutex_unlock(&table_mutex); } // 定时扫描函数 void arp_scan() { uint8_t src_mac[6]; uint32_t src_ip; const char *interface = "ens37"; get_mac_address(interface, src_mac); get_ip_address(interface, &src_ip); int sock = create_arp_socket(); // 启动ARP表管理线程 pthread_t manager_thread; pthread_create(&manager_thread, NULL, arp_table_manager, NULL); while (1) { if (config.enable) { time_t now = time(NULL); struct tm *tm_info = localtime(&now); char time_str[20]; strftime(time_str, 20, "%Y-%m-%d %H:%M:%S", tm_info); printf("\n[%s] 开始ARP扫描 (范围: %u-%u)", time_str, ntohl(config.start_ip), ntohl(config.end_ip)); // 扫描指定IP范围 uint32_t start = ntohl(config.start_ip); uint32_t end = ntohl(config.end_ip); for (uint32_t ip = start; ip <= end; ip++) { if (ip == ntohl(src_ip)) continue; // 跳过本机 uint32_t target_ip = htonl(ip); send_arp_request(sock, interface, src_ip, src_mac, target_ip); // 按配置的发包间隔等待 if (config.packet_interval > 0) { usleep(config.packet_interval * 1000); } } // 接收响应 receive_arp_response(sock, src_mac); // 打印当前ARP表 print_arp_table(); } // 按配置的扫描周期等待 sleep(config.scan_interval); } } // 开始扫描 void arp_start() { // 设置用户配置 config.enable = 1; config.scan_interval = 2; // 60秒扫描周期 config.entry_timeout = 300; // 300秒有效期 config.packet_interval = 100; // 100毫秒发包间隔 // 设置扫描范围: 192.168.1.100 - 192.168.1.200 inet_pton(AF_INET, "192.168.63.65", &config.start_ip); inet_pton(AF_INET, "192.168.63.75", &config.end_ip); // 打印初始配置 print_config(); arp_scan(); } int main() { arp_start(); return 0; } 修改该代码 使其包含以下函数功能 set_arp_config(设置功能开关、扫描周期、有效期、发包间隔、起始IP、结束IP地址) get_arp_config(获取功能开关、扫描周期、有效期、发包间隔、起始IP、结束IP地址) start_scan(开始一次扫描) stop_scan(停止扫描) get_scan_status(扫描状态) get_scan_result(获取最近一次的扫描结果) clear_result(清除历史结果)
最新发布
08-28
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值