动图:

ip_file.h:

#ifndef IP_FILE_H
#define IP_FILE_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>//*************************过滤链表******************************
typedef struct myrouter
{unsigned char ip[32] ;struct myrouter* next;
}MY_ROU;//释放链表
extern MY_ROU* rou_freeLink(MY_ROU *head);
//尾插
extern MY_ROU *rou_pTailInsert(MY_ROU *head);
//遍历
extern void rou_print_link(MY_ROU *head);
//查找ip
extern int rou_searcharpLink(MY_ROU *head,char *ip);
//删除
extern MY_ROU *rou_pDeleteLink(MY_ROU *head);
//*************************过滤链表******************************/******************************************************************
函   数:  void init_ip_link()
功   能:  读取配置文件数据到链表
参   数:  无
返回值: 无
*******************************************************************/
extern void init_ip_link();/******************************************************************
函   数:  IP_LINK *find_ip(IP_LINK *head, unsigned char *ip)
功   能:  插入ip过滤链表
参   数:  IP_LINK *head ip过滤链表头  IP_LINK* p 待插入节点
返回值: IP_LINK *找到的节点
*******************************************************************/
extern MY_ROU *inner_ip_link(MY_ROU *head,MY_ROU* p);/******************************************************************
函   数:  void save_ip_link()
功   能:  保存链表数据到配置文件
参   数:  无
返回值: 无
*******************************************************************/
extern void save_ip_link();#endif

ip_file.c:–与main.c共用一个结构体指针变量,保存过滤IP链表头节点

//与main.c共用一个结构体指针变量,保存过滤IP链表头节点
MY_ROU * roulink_head = NULL;

.
.

#include "ip_file.h"
#define ip_config_name "ip_config"//与main.c共用一个结构体指针变量,保存过滤IP链表头节点
MY_ROU * roulink_head = NULL;//--------------------操作文件中的过滤IP----------------------//
void init_ip_link()
{FILE *ip_config = NULL;ip_config = fopen(ip_config_name,"rb+");if(ip_config == NULL){perror("!!!configure file,in main.c");_exit(1);}puts("filter IP:");int i = 0;while(1){char buff[500]="";bzero(buff, sizeof(buff));int ip;if(fgets(buff, sizeof(buff), ip_config) == NULL){printf("ip_config 文件为空\n");break;}if(strlen(buff) < 7)//1.1.1.1{break;}buff[strlen(buff)-1]=0;//注意文件中存在\r//printf("IP[%d] = %s\n",i++,buff);inet_pton(AF_INET, buff, &ip);MY_ROU *pb = (MY_ROU *)malloc(sizeof(MY_ROU));   char ip_buf[16] = "";inet_ntop(AF_INET, &ip, ip_buf, 16);//printf("ip_buf[%d] = %s\n", ++i, ip_buf);//strcpy(pb->ip, ip_buf);memcpy(pb->ip, ip_buf, 16);printf("pb->ip[%d] = %s\n", i, pb->ip);//传入变化的头节点 + 带有IP信息的结构体指针变量roulink_head = inner_ip_link(roulink_head, pb);i++;}//rou_print_link(ip_head);fclose(ip_config);
}MY_ROU *inner_ip_link(MY_ROU *head, MY_ROU* p)
{// head = (MY_ROU*)malloc(sizeof(MY_ROU));     //创建头结点 // head->next = NULL;MY_ROU * pb = head;int a = rou_searcharpLink(head, p->ip);//查找是否有该记录if(a == 0){if(pb==NULL){//未查找到,插入链表,直接插入表头方便p->next = NULL;head = p;}else{           #if 1  //头插法--寻找插入的节点              MY_ROU * p2_new = (MY_ROU*)malloc(sizeof(MY_ROU)); strcpy(p2_new->ip, p->ip);// printf("继续头插!!!!p2_new->ip = %s!!!!!!\n",p2_new->ip);p2_new->next = pb->next;pb->next = p2_new;#endif                                  #if 0 //尾插法--正确MY_ROU *p1=pb;while(p1->next!=NULL){p1=p1->next;}//插入p1->next=p;  #endif             }}return head;
}void save_ip_link()
{FILE *ip_config = fopen(ip_config_name,"wb+");if(ip_config == NULL){perror("!!!configure file,in main.c");_exit(1);}char buff[20]="";MY_ROU *pb=roulink_head;while(pb != NULL){printf("!保存2命令输入IP\n");memcpy(buff, pb->ip, 16);//一次拷贝16个字节buff[strlen(buff)+1]='\n';//注意文件中存在\r//一个IP新切换一行保存到文件fprintf(ip_config, "%s\n", buff);pb = pb->next;}fclose(ip_config);
}
//--------------------操作文件中的过滤IP----------------------////*************************过滤链表******************************//
//尾插
MY_ROU *rou_pTailInsert(MY_ROU *head)
{//申请一个待插入的空间MY_ROU *pi=(MY_ROU*)malloc(sizeof(MY_ROU));pi->next=NULL;printf("输入过滤ip:");//向空间中插入数据scanf("%s",pi->ip);//判断是否有数据if(head==NULL){head=pi;}else{//寻找插入的节点MY_ROU *p1=head;while(p1->next!=NULL){p1=p1->next;}//插入p1->next=pi;}printf("设置完成\n");return head;
}//遍历
void rou_print_link(MY_ROU *head)
{if(head==NULL){printf("没有数据\n");}else{while(head!=NULL){printf("ip:%s\n",head->ip);head=head->next;}}return;
}//释放链表
MY_ROU* rou_freeLink(MY_ROU *head)
{MY_ROU *pd;pd=head;while(head!=NULL){head=pd->next;free(pd);pd=head;}printf("过滤链表释放完毕\n");return head;
}//查找ip
int rou_searcharpLink(MY_ROU *head,char *ip)
{MY_ROU * pb = head;int i=0;while(pb!=NULL){if(strcmp(ip, pb->ip)==0){i++;//printf("存在相同ip\n");return 1;}pb = pb->next;}if(0==i){//printf("未找到ip\n");return 0;}
}//删除
MY_ROU *rou_pDeleteLink(MY_ROU *head)
{char num[16]="";MY_ROU *pe=head;MY_ROU *pf=head;printf("请输入你要删除的ip:");scanf("%s",num);if(NULL==head){printf("无可删除数据\n");}else{while(strcmp(pe->ip,num)){pf=pe;pe=pe->next;if(NULL==pf->next){printf("未找到要删除数据\n");return head;}}if(pe==head){head=pe->next;free(pe);}else{pf->next=pe->next;free(pe);}}return head;
}
//*************************过滤链表******************************

main.c:–与ip_file.c共用了一个过滤IP链表的头节点

extern MY_ROU * roulink_head;//与ip_file.c共用一个结构体指针变量,保存过滤IP链表头节点

.
.

#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <netinet/ether.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netpacket/packet.h>
#include <sys/ioctl.h>
#include "get_interface.h"
#include "arp_link.h"
#include"ip_file.h"extern MY_ROU * roulink_head;//与ip_file.c共用一个结构体指针变量,保存过滤IP链表头节点
MY_ARP * arplink_head = NULL;
int sockfd = 0;
//*************************人机交互线程**********************************
void *callback1(void *arg)
{ while(1){  printf("输入相应的序号,实现对应功能\n");int usercmd = -1;scanf("%d", &usercmd);switch (usercmd){case 0:getchar();title();break;case 2:                    getchar();//接收输入2的回车roulink_head=rou_pTailInsert(roulink_head);break;        case 3:getchar();roulink_head=rou_pDeleteLink(roulink_head);break;case 4:getchar();rou_print_link(roulink_head);/*将指针pHead传入输出函数遍历输出*/           printf("链表打印完毕!\n");break;        case 5:arp_print_link(arplink_head);break;case 6:save_ip_link();break;case 10:printf("10:退出路由器,释放IP、ARP链表\n");getchar();arp_freeLink(arplink_head);rou_freeLink(roulink_head);//释放链表exit(1);break;}}pthread_exit(NULL);
}
//*************************人机交互线程**********************************//*************************ARP应答的IP和MAC存入缓存链表线程【开始】**************//
void * callback2_arp(void *arg)
{arp_mac_ip *p = (arp_mac_ip*)arg;//printf("将 ARP 应答的 IP 和 MAC 存入缓存链\n");//printf("### %s\n", p->stc_ip);if(arp_searcharpLink(arplink_head, p->stc_ip) == 0){//printf("插入链表中没有的ARP 应答 IP 和 MAC\n");arplink_head = arp_pTailInsert( arplink_head, p->stc_mac ,p->stc_ip);}pthread_exit(NULL);
}
//*************************ARP应答的IP和MAC存入缓存链表线程【结束】***************////*************************IP包转发线程【开始】**********************************//
void *callback3_ip(void *arg)
{//发送接口的结构体struct sockaddr_ll sll;ip_buf *pthread_ip_buf = (ip_buf *)arg;unsigned char * ip_head= pthread_ip_buf->buf + 14;char dst_ip[16] = "";inet_ntop(AF_INET, ip_head + 16, dst_ip, 16);printf("IP包转发线程中 目的 dst_ip = %s\n", dst_ip);int i = 0;for (i = 0; i < 16; i++){unsigned char ip[16]=""; inet_ntop(AF_INET,net_interface[i].ip, ip, 16);//get_interface文件中得到的都是32位无符号整形数据(计算机数据),现转成成点分十进制(人能够书别的)//---------------------[调试]----------------------------------------////printf("设置网卡循环进入次数 i = %d\n", i);//printf("检索到的所有网卡名字net_interface[i].name = %s\n", net_interface[i].name);//printf("net_interface[i].ip = %s\n",ip);//---------------------[调试]----------------------------------------//if(strncmp(ip,  dst_ip, 9) == 0)//根据目标网段 查找活跃网卡{   //网卡结构体struct ifreq ethreq;strncpy(ethreq.ifr_name, net_interface[i].name , IFNAMSIZ);//指定网卡名字printf("网卡名字:%s\n", ethreq.ifr_name);if(ioctl(sockfd, SIOCGIFINDEX, &ethreq) == -1)//获取网卡接口地址{return 0;}bzero(&sll, sizeof(sll));sll.sll_ifindex = ethreq.ifr_ifindex;//将网卡的接口类型赋值给发送接口break;}else{//printf("找不到网段对应的网卡,继续查\n");continue;}}//--------------------------------------------拿到网卡,开始检索对应网卡所有数据,对比【开始】------------------------------------------------------//if(strcmp(dst_ip + strlen(dst_ip) - 3, "255") == 0)//是 否为广 播地址{// printf("是广播地址, 退出线\n"); return;              }else{//printf("不是广播地址,判断是否为回 环地址\n");if(strcmp("127.0.0.1",  dst_ip) == 0){//printf("是回 环地址, 退出线\n");return;                      }else{//printf("查找ARP缓存表 对应 MAC\n");//指定目的MAC地址//可以在链表中找到目的IP,组ICMP包的目的MAC就可以了//之所以这样,是因为在网络中的ICMP包里,变化的只有目的MAC,源MAC、IP都不会发生变动if(arp_searcharpLink(arplink_head, dst_ip) == 1){  //1网段中 指定目标IP是主机的IP、MAC//2C-4D-54-57-04-7F//printf("****icmp****\n");if(strncmp("192.168.1.49", dst_ip, 9) == 0){pthread_ip_buf->buf[0]=0x2C;pthread_ip_buf->buf[1]=0x4D;pthread_ip_buf->buf[2]=0x54;pthread_ip_buf->buf[3]=0x57;pthread_ip_buf->buf[4]=0x04;pthread_ip_buf->buf[5]=0x7F;//目标int send_len = sendto(sockfd, pthread_ip_buf->buf, pthread_ip_buf->my_buf_date_len, 0, (struct sockaddr *)&sll, sizeof(sll));//-------------------[调试]------------------------////printf("****1 网段 icmp缓存表****\n");   // printf("send_len ICMP 1 = %d\n", send_len);//-------------------[调试]------------------------//}//2网段中 指定目标IP是开发板的IP、MAC//  00:53:50:00:01:33else if(strncmp("192.168.2.100", dst_ip, 9) == 0){                   pthread_ip_buf->buf[0]=0x00;pthread_ip_buf->buf[1]=0x53;pthread_ip_buf->buf[2]=0x50;pthread_ip_buf->buf[3]=0x00;pthread_ip_buf->buf[4]=0x59;pthread_ip_buf->buf[5]=0x12;//发送给套接字的数据长度,是实际传送过来的长度(main中的IP包有收到具体长度信息)int send_len = sendto(sockfd, pthread_ip_buf->buf, pthread_ip_buf->my_buf_date_len, 0, (struct sockaddr *)&sll, sizeof(sll));//-------------------[调试]------------------------////printf("****2 网段 icmp缓存表****\n");   // printf("send_len ICMP 2 = %d\n", send_len);//-------------------[调试]------------------------//}}else{//没在链表中没有找到目的IP,需要重新组arp包才行//printf("***************组ARP包\n");int i = 0;for(; i < 3; i++){     //printf("%s\n",dst_ip);  //比对到1网段的数据             if(strstr(dst_ip,"192.168.1") != 0)                      {printf("发送网段1arp包\n");unsigned char arp_buf[42] = {0xff,0xff,0xff,0xff,0xff,0xff,//目的mac,广播的形式发出去,等待目的IP恢复后覆盖0x00,0x0c,0x29,0xfa,0x7c,0x9e,//源mac0x08, 0x00,//协议类型0, 1,//硬件类型6,4,0, 1,//op0x00,0x0c,0x29,0xfa,0x7c,0x9e,//源mac(网卡1 ech0的MAC)192,168,1,88,//源IP是路由器1网段的网关,通过它发送到2网段0x00,0x00,0x00,0x00,0x00,0x00,//目的mac,等待目的IP恢复后覆盖0,0,0,0//192,168,1,49,};int int_ip=0;inet_pton(AF_INET, dst_ip, &int_ip);unsigned char *intp=(char *)&int_ip;arp_buf[38]=intp[0];arp_buf[39]=intp[1];arp_buf[40]=intp[2];arp_buf[41]=intp[3];int send_len = sendto(sockfd, arp_buf, sizeof(arp_buf), 0, (struct sockaddr *)&sll, sizeof(sll));printf("send_len 11 = %d\n",send_len);}//网卡2,ech1的MAC:00:0c:29:fa:7c:a8else if(strstr(dst_ip,"192.168.2") != 0)                      {printf("发送网段2arp包\n");unsigned char arp_buf[42] = {0xff,0xff,0xff,0xff,0xff,0xff,//目的mac0x00,0x0c,0x29,0xfa,0x7c,0xa8,//源mac0x08, 0x00,//协议类型0, 1,//硬件类型6,4,0, 1,//op0x00,0x0c,0x29,0xfa,0x7c,0xa8,//源mac192,168,2,89,//源IP是路由器2网段的网关,通过它发送到1网段0x00,0x00,0x00,0x00,0x00,0x00,//目的mac192,168,2,100,};int send_len = sendto(sockfd, arp_buf, sizeof(arp_buf), 0, (struct sockaddr *)&sll, sizeof(sll));printf("send_len 22 = %d\n",send_len);}if(arp_searcharpLink(arplink_head, dst_ip) == 1){//1//2C-4D-54-57-04-7Fif(strncmp("192.168.1.49", dst_ip, 9) == 0){pthread_ip_buf->buf[0] =  0x2C;pthread_ip_buf->buf[1] =  0x4D;pthread_ip_buf->buf[2] =  0x54;pthread_ip_buf->buf[3] =  0x57;pthread_ip_buf->buf[4] =  0x04;pthread_ip_buf->buf[5] =  0x7F;int send_len = sendto(sockfd, pthread_ip_buf->buf, pthread_ip_buf->my_buf_date_len, 0, (struct sockaddr *)&sll, sizeof(sll));//-------------------[调试]------------------------////printf("****3次发ARP过程中检索到ICMP包 1 网段****\n");   // printf("send_len ICMP 1 = %d\n", send_len);//-------------------[调试]------------------------//}//2// 开发板MAC(每次启动都会变化):00:53:50:00:3B:DBelse if(strncmp("192.168.2.100", dst_ip, 9) == 0){pthread_ip_buf->buf[0] =  0x00;pthread_ip_buf->buf[1] =  0x53;pthread_ip_buf->buf[2] =  0x50;pthread_ip_buf->buf[3] =  0x00;pthread_ip_buf->buf[4] =  0x59;pthread_ip_buf->buf[5] =  0x12;int send_len = sendto(sockfd, pthread_ip_buf->buf, pthread_ip_buf->my_buf_date_len, 0, (struct sockaddr *)&sll, sizeof(sll));//-------------------[调试]------------------------////printf("****3次发ARP过程中检索到ICMP包 2 网段****\n");   // printf("send_len ICMP 2 = %d\n", send_len);//-------------------[调试]------------------------//}break;}}}return;}} //--------------------------------------------拿到网卡,开始检索对应网卡所有数据,对比【结束】------------------------------------------------------//pthread_exit(NULL);}
//*************************建IP包转发线程【结束】**********************************//int main()
{//初始化 配置文件init_ip_link();//创建原始套接字,接收发送方的网卡信息sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));if(sockfd<0){perror("sockfd:");return 0;}getinterface();//拿取网卡信息(虚拟机的所有网卡,包括回环网卡)pthread_t pth;pthread_create(&pth, NULL, callback1, NULL);//人机交互线程,这里可以放在main里面int len = 0;char recv_buff[RECV_SIZE]="";//原始套接字数据包大约为1500个字节ssize_t recv_len=0;while(1){              //开始接收其他人的网卡信息bzero(recv_buff,sizeof(recv_buff));//[recv_len]设置成全局变量,让线程可以共用数据recv_len = recvfrom(sockfd, recv_buff, sizeof(recv_buff), 0,  NULL, NULL);if(recv_len<=0||recv_len>RECV_SIZE){perror("recvfrom");continue;}//printf("链路层截取数据包长度 recv_len=%d\n",recv_len);//MAC包类型unsigned short mac_type = 0;mac_type = ntohs( *((unsigned short *)(recv_buff + 12)));if(mac_type == 0x0800){//printf("-----------ip数据包------------\n");unsigned char *ip_head = recv_buff + 14; unsigned char dst_ip[16] ="";inet_ntop(AF_INET, ip_head + 16, dst_ip, 16);//IP包的类型if(ip_head[9] == 1){//printf("-----ICMP数据包\n");//查找过滤IP链表中存在我们指定的目的IP吗if(rou_searcharpLink(roulink_head, dst_ip) == 0){static int i=0;//-----------调试,打印原始套接字接收到的数据内容是否是空--------------------//           //printf("i=%d   IP包中的目的IP = %d\n",++i, strlen(recv_buff + 30));                             // printf("Rvfbuf=%p\n",recv_buff);// int kk=0;// while(kk<98)// {//     printf("Rvfbuf[%d]=%d\n",kk,recv_buff[kk]);//     kk++;// }//----------------------------[调试]---------------------------------------//usleep(1000); ip_buf *recv = (ip_buf *)malloc(sizeof(ip_buf));recv->my_buf_date_len = recv_len;memcpy(recv->buf, recv_buff, recv_len);//线程的创建放在满足它的条件中,while循环,满足就进来创建一个,切记不要放到条件外面创建线程,否则只会创建一个,导致所有情况共用一个线程pthread_t pth2;//最后数据包是ICMP的整包pthread_create(&pth2, NULL, callback3_ip, (void*)recv);pthread_detach(pth2);}}}else if(mac_type == 0x0806){           arp_mac_ip * head_mac_ip = NULL;//保存目的MAC\IP的结构体,安全措施,防止栈空间释放导致给线程传参为空,失败head_mac_ip = (arp_mac_ip *)malloc(sizeof(arp_mac_ip ));unsigned char *arp_head = recv_buff + 14;unsigned char * arp_src_mac =  arp_head + 8;//跳过[4.硬件类型、5.协议类型、6.硬件地址长度、7.协议地址长度、8.OP,拿到源MAC地址首地址信息]unsigned char stc_mac[18] = "";sprintf(stc_mac, "%02x:%02x:%02x:%02x:%02x:%02x", arp_src_mac[0],\arp_src_mac[1],\arp_src_mac[2], \arp_src_mac[3],\arp_src_mac[4], \arp_src_mac[5]);strcpy(head_mac_ip->stc_mac, stc_mac);unsigned char src_ip[16]  = "";inet_ntop(AF_INET, arp_head + 14, src_ip, 16);//拿到源IP           strcpy(head_mac_ip->stc_ip, src_ip);//-----------------------------------[调试]-----------------------------------//   //printf("-----------arp数据包------------\n");//printf("arp 源mac:%s\n",head_mac_ip->stc_mac);        //printf("arp 源IP:src_ip = %s  \n", src_ip); //-----------------------------------[调试]-----------------------------------//  //线程中只保存源ARP的MAC、IP,目的主机的MAC、IP,在IP线程中指定(写死)pthread_t pth1;pthread_create(&pth1, NULL, callback2_arp, (void*)head_mac_ip);pthread_detach(pth1);}}return 0;
}

146_路由器项目_附加功能:可以拿取文件内IP保存到过滤链表中,过滤IP也可以保存到txt文件,也可以终端输入IP,保存到文件【单链表的尾插、头插、删除指定节点、遍历等】】相关推荐

  1. C语言下链表数据保存到.txt文件失败

    问题描述 保存链表中的数据的代码 int readin3(ConRecNode* head) {ListConRec p = head->next;FILE* fp;char fileName[ ...

  2. C语言的双向链表头插法和尾插法,指定节点删除

    文章目录 前言 头插法 尾插法 删除节点 测试代码如下 前言 双向链表和单链表的唯一区别就是多个一个指针域而已,该指针域可以访问链表的上一个节点. 关于构造双向链表的过程我们常见的有两种方法,和单链表 ...

  3. Jquery删除指定节点下的所有元素

    Jquery删除指定节点下的所有元素 在使用jquery编写网页的时候最常用的删除节点的方法包括三种: $(selector).remove():remove方法会删除被选元素(即selector), ...

  4. R语言使用pdf函数将可视化图像结果保存到pdf文件中、使用pdf函数打开图像设备、使用dev.off函数关闭图像设备、自定义width参数和height参数指定图像的宽度和高度

    R语言使用pdf函数将可视化图像结果保存到pdf文件中.使用pdf函数打开图像设备.使用dev.off函数关闭图像设备.自定义width参数和height参数指定图像的宽度和高度 目录

  5. R语言使用pdf函数将可视化图像结果保存到pdf文件中、使用pdf函数打开图像设备、使用dev.off函数关闭图像设备、自定义paper参数指定pdf的纸张类型(多使用A4)

    R语言使用pdf函数将可视化图像结果保存到pdf文件中.使用pdf函数打开图像设备.使用dev.off函数关闭图像设备.自定义paper参数指定pdf的纸张类型(多使用A4) 目录

  6. 头插法和尾插法建立带头节点的单链表

    有两种方法建立单链表,尾插法和头插法,他们的区别是:头插法是按照输入元素倒序建立,为尾插法为顺序插入,并且多一个尾节点,我们一般使用尾插法. 一.头插法 代码为: pCurr -> next = ...

  7. 单链表之o(1)删除指定节点(Java)

    思路: 1.如果删除的节点不是尾节点,只需要把下一个节点的值复制到当前节点,然后当前节点指向下下个节点即可 2.如果删除的是尾节点, 链表只有一个元素,直接删除即可: 遍历找到尾节点的前一个节点,把此 ...

  8. 单链表删除指定节点c语言,在单链表删除指定节点之后的节点

    要删除在指定节点之后存在的节点,需要跳过所需数量的节点以到达节点,之后的节点将被删除. 需要跟踪这两个节点.如果在该节点之前存在的节点,则将删除该节点. 为此,使用了两个指针:ptr和ptr1. 使用 ...

  9. 2021_01_11_实习实训_day07_员工后台管理项目_编辑功能以及分页查询功能

    实习实训 项目empManeger_2021 编辑功能 前台实现 编辑按钮 获取学生信息 返回前台 后台实现 相关数据库接口与方法 数据库接口方法 getEmpByEmpno声明 数据库接口方法 ed ...

最新文章

  1. Talairach空间、MNI空间、Native空间、Stereotaxic空间
  2. Java数据结构和算法(三)——冒泡、选择、插入排序算法
  3. 基于DDD的.NET开发框架 - ABP模块设计
  4. why in GM0 our extension component this.sPath is not correct
  5. LR中如何添加事务,参数化,检查点,集合点,思考时间等
  6. java 内部类 作用_java内部类的作用分析
  7. easyexcel导入简单封装
  8. 手写邮箱获取验证码注册登录功能
  9. 在RedHat Enterprise Linux 上Oracle 9i的安装配置与调优
  10. 深入解析字符串的比较方法:“==”操作符;String.Equals方法;String.Compare方法;String.CompareOrdinal方法。...
  11. 2021大学生创业计划书范例
  12. android soundpool 封装,Android SoundPool的简单使用
  13. QListView的使用方法
  14. 【网络攻防课实验】一:本地系统密码破解
  15. 制作自己的字体图标库
  16. 2021最新外卖霸王餐小程序、H5、微信公众号版外系统源码|霸王餐美团/饿了么系统 粉丝裂变玩源码下载
  17. es6箭头函数_【知识点】ES6箭头函数、箭头函数与普通函数的区别
  18. Linux文件权限:特殊权限、权限属性、权限掩码
  19. http请求时返回的304是干什么的
  20. 越狱Season 1-Episode 12:Odd Man Out

热门文章

  1. VSCode 保存时 ESLint 一键修复
  2. 高空抛物检测(侦测)系统为您撑起一把安全之伞
  3. 小程聊微服务-自己动手扩展分布式调用链
  4. 高级职称17计算机,(高级职称计算机考试.doc
  5. OFD文档标准 2.主入口文档
  6. 四川大学江安校区计算机学院照片,几张图告诉你四川大学江安校区颜值到底有多高...
  7. WriteFile 错误(GetLastError)返回998
  8. Axure RP原型发布到公司服务器
  9. 第四次作业类测试代码+108+曾宏宇
  10. windows开机密码问题