




免费预览已结束,剩余19页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
ping程序设计ping命令是使用频率极高的一个网络测试命令,用以测试从一个主机到另一个主机间的网络上否可达。windows自带的ping命令具有强大的功能,它有很多选项用于实现不同的测试目的。本章模仿windows的ping命令,用c语言实现了一个简单的命令。本章着重讲述ping命令的实现原理和c语言的网络编程方法。读者可以在本章的基础上,对本章实现的ping命令进行扩展,开发出功能更强大、更完善的ping命令,并进一步掌握网络编程的方法。9.1 设计目的本章通过设计Ping程序,讲解Ping程序的实现原理,并初步讲解了c语言网络编程技术。本章涉及很多网络编程函数和编程技巧。包括库文件的导入;winsock的初始化、注销;socket的创建、关闭;设置socket选项;根据主机名获取IP地址; 从堆中分配一定数量的空间、释放从堆中分配的空间;获取当前进程ID号;数据报的发送;数据报的接等。 通过本程序的训练,使读者对网络编程有一定的了解,掌握Ping程序的设计方法,掌握网络编程的方法和技巧,从而编写出功能更强大的程序。9.2功能描述本章用 c 语言实现的 ping命令,能用于测试一个主机到另一个主机间的联通情况,程序还提供了几个选项以实现不同的功能。(1)实现ping功能。程序能实现基本的ping操作,发送ICMP回显请求报文,接收显应答报文。(2)能记录路由。程序提供了“-r”选项,用以记录从源主机到目的主机的路由。(3)能输出指定条数的记录。程序提供了“-n”选项,用以输出指定条数的记录。(4)能按照指定大小输出每条记录。程序提供了“datasize”选项,用以指定输出的数据报的大小。(5)能输出用户帮助。程序提供了用户帮助,显示程序提供的选项以及选项格式等。9.3 总体设计9.3.1 功能模块设计1. 功能模块图本系统共有 4 个模块,分别是初始化模块、功能控制模块、数据控制模块、数据报解读模块和ping测试模块,如图9.1所示。各模块功能描述如下。Ping程序设计初始化模块数据报解读模块功能控制模块Ping测试模块图 9.1 系统模块图(1) 初始化模块。该模块用于初始化各个全局变量,为全局变量赋初始值;初始化,加载库。(2)功能控制模块。该模块是被其它模块调用,其功能包括获取参数、计算校验和填充数据报文、释放占用资源和显示用户帮助。(3)数据报解读模块。该模块用于解读接收到的报文和选项。(4)测试模块。该模块是本程序的核心模块,调用其他模块实现其功能,主要是实现的功能。 2系统流程图系统执行的流程图9.2所示。程序首先调用IniPing()函数初始化各全局变量,然后GetArgments()函数获取用户输入的参数,检查用户输入的参数,如果参数不正确或者没有输入参数,则显示用户帮助信息(User help ),并结束程序;如果参数正确,则对指定目的地执行Ping命令,如果Ping通,则显示Ping结果并释放占用资源,如果没有Ping通,则报告错误信息,并释放占用资源。开始初始化个变量获取参数信息输入参数是否正确?Ping目的地Ping成功?输出Ping结果释放占用资源结束输出错误信息显示帮助信息图9.2 系统流程图3.参数获取(GetArgments()函数)流程图获取的参数包括“-r”(记录路由)、“-n”(记录条数程序,任意的整数)和datasize(数据报大小)。程序首先判断每一个参数的第一字符,如果第一个字符是“-”(短横线),则认为是“-r”或者“-n”中的一个,然后作进一步判断。如果该参数的第二个字符是数字,则判断该参数为记录的条数,如果该参数的第二个字符是“r”,则判断该参数为“-r”, 用于记录路由;如果参数的第一个字符是数字,则认为 参数是IP地址;或者datasize,然后作进一步的判断。如果该参数中不存在非数字的字符, 则判断该参数为datasize;如果存在非数 字的字符,则判断该参数为IP地址;其他情况则判断为主机名。参数获取的流程如图9.3所示。开始Argc=1?检查第一i个参数的第一个字符是“-”?检查第一i个参数的第二个字符是数字?该参数表示要获取的记录数转换成十进制记录到全局变量packetNUM还有参数?结束是数字?该参数中有非数字字符?该参数表示IP地址该参数表示数据报大小该参数表示主机名是“r”?显示用户帮助设标志位RecordFlag为tureI=i+1记录到变量Lpdest中记录到变量Datasize中记录到变量Lpdest中图9.3 参数获取流程图4.ping()函数流程图ping()函数是本程序的核心部分它调用其他模块的函数来实现,其主要步骤包括创建接字,设置路由选项(如果需要的话)、设置接收和发送超时值、名字解析(如果需要的话)、分配内存、创建ICMP报文、发送ICMP请求报文、接收ICMP应答报文和解读ICMP报文。其执行流程如图9.4所示。开始创建原始套接字创建成功?记录路由?设置接收和发送超时值为每个ICMP设置路由选项设置成功?名字解析?根据主机名获取各种参数获取成功?设置目的地址各项字段根据ICMP报文大小分配内存分配成功创建ICMP报文发送ICMP请求发送成功?超时发送?输出超时发送接收ICMP应答输出失败信息 接收成功?超时接收?输出失败信息输出超时接收读取ICMP数据报文记录数达到指定值?图9.4 Ping 函数流程图 9.3.2数据结构设计 本程序定义了3个结构体:-iphdr、-icmphdr、和-ipotionhdr,分别用于存放IP报头信息、ICM P报头信息和IP路由选项信息。1. 定义IP报头结构体IP数据报头格式如下图: Typedef struct _iphdr Unsigned int h_len:4;Unsigned int version:4;Unsigned char tos;Unsigned short total_len;Unsigned short ident;Unsigned short frag_flags;Unsigned char ttl;Unsigned chor proto;Unsigned short checksum;Unsigned int sourceIP;Unsigned int destIP; IpHeader; 其中各字段表示意义如下。 h-len:4 : 表示IP报头长度,首部长度指的是首部占32bit字的数目,包括任何选项。由于它是一个4bit 字段,因此首部最长为60个字节,不包括任何选项的IP报头是20个字节。 Version:4: 表示IP的版本号,这里表示Ipv4.。 Top: 表示服务的类型,可以表示最小时延,最大吞吐量,最高可靠性和最小费用。 Total len: 整个IP数据报的总长度。 Ident: 唯一的标识符,标识主机发送的每一份数据报。 Frag-flags: 分段标志,表示过长的数据报是否要分段。 Ttl: 生存期,表示数据报可以经过的最多路由器数。 Proto: 协议类型(TCP、UDP等)。 Checksum: 校验和。 sourceIP: 源IP地址。destIP: 目的IP地址。2. 定义报头结构体ICMP(网间网控制报文协议)协议应用广泛。在此仅给出最常见的回应请求与应答报文格式,用户命令ping便是利用此报文来测试信宿机的可到达性。报文格式如下图所示: 类型0 为回应应答报文,8 为回应请求报文。整个数据包均参与检验。注意ICMP封装在IP数据包里传送。Typedef struct icmphdr BYTE i_type; BYTE i_code : USHORT i_cksum; USHORT i_id; USHORT i_seq; ULONG timestamp; IcmpHeader; 其中各字段表示意义如下。 I_type : 报文类型。I_code : 该类型中的代码号,一种ICMP 报文的类型号和该类型中的代码号共同决定。、 I_cksum: 校验和。 I_seq: 序列号,序列号从0开始,每发送一次新的回显请求就加1. Timestamp: 时间。3. 定义IP 选项结构体IP首部中有4bit用于表示首部长度,其单位是4个字节,所以,IP首部的最大长度是15*4=60字节,而IP固定首部的长度是20字节,所以一个IP首部最大允许有40字节长度的选项。 IP选项的一般格式是1个字节的代码(code),一个字节的长度(len),一个字节的指针(ptr),指针的值从1开始计数,指向IP选项的内容,一 般其值为4(跳过前面3字节的code, len, ptr),长度包括前面3字节在内的整个IP选项,最大值为40。 代码表示不同类型的IP选项,其可能的取值有: IPOPT_END,值为0,表示IP首部的选项到此结束。该选项就一个code,总长度为1。 IPOPT_NOOP,值为1,表示无操作。用作占位符,因为IP选项的总长度需要为4的整数倍。 IPOPT_SEC,值为0x82,意义暂不明,从代码来看,并未对其作任何实际操作。 IPOPT_SID,值为0x88,意义暂不明,从代码来看,未对其作任何实际操作。 IPOPT_LSRR,值为0x83,表示宽松的源站路由选项,该选项ptr指向的位置开始是一组表示IP地址的32位无符号数,指明本机上该 socket发送的数据报必须经过这一组IP地址中的每一个,但是任意两个地址之间还可以通过其他路由器(这就是宽松的含义)。 IPOPT_SSRR,值为0x89,表示严格的源站路由选项,即IP地址列表指明数据报必须采用的精确路由。 IPOPT_TIMESTAMP,值为0x44,表示IP时间戳选项,该选项除了前三个字节为code,len,ptr,第四字节前4bit表示溢出字段 (OF),后4bit表示标志字段(FL),FL有三个可能的取值IPOPT_TS_TSONLY(0),表示只记录时间戳; IPOPT_TS_TSANDADDR(1),表示每个路由器都记录它的IP地址和时间戳,这样,在列表中就只能存放4对地址和时间戳; IPOPT_TS_PRESPEC(2),表示发送端对选项列表进行初始化,存放了4个IP地址和4个取值为0的时间戳值。只有当列表中的下一个IP地址 与当前路由器地址相匹配时,才记录它的时间戳。由于IP选项的长度有限,当路由器由于没有空间而不能增加时间戳选项时,它将增加溢出字段(OF)的值。 IPOPT_RR,值为0x07,表示IP记录路由选项,其格式跟IPOPT_LSRR相同,每一个路由器都把自己的出口IP地址记录到该选项的IP清单中,以达到记录路由的目的。ping程序的-R选项支持记录路由的功能。 IPOPT_RA,值为0x94,具体用途暂不明,跟路由和转发相关。 Linux内核用结构体struct ip_options表示IP选项,其定义如下: struct ip_options _u32 faddr; unsigned char optlen; unsigned char srr; unsigned char rr; unsigned char ts; unsigned char is_setbyuser:1, is_data:1, is_strictroute:1, srr_is_hit:1, is_changed:1, rr_needaddr:1, ts_needtime:1, ts_needaddr:1; unsigned char router_alert; unsigned char _pad1; unsigned char _pad2; unsigned char _data0; ; faddr用于在IPOPT_LSRR和IPOPT_SSRR选项时,记录下一站的IP地址,optlen是IP首部中选项所占据的长度,srr记录 IPOPT_LSRR或IPOPT_SSRR选项在IP首部中的偏移量(选项的第一个字节的地址减去IP首部的第一个字节的地址),rr用于记录 IPOPT_RR选项在IP首部中的偏移量,ts用于记录IPOPT_TIMESTAMP选项在IP首部中的偏移量。 接下来是一些标志位,is_setbyuser表示该IP选项是应用层通过setsockopt设置的,is_data表示该IP选项拥有数据,选项数据存放在_data中。is_strictroute表示该选项是IPOPT_SSRR,而不是IPOPT_LSRR。 srr_is_hit跟源站路由选项相关,对IP选项作过任何的修改,需要把is_changed置1,rr_needaddr表示有IPOPT_RR选 项,需要记录IP地址,ts_needtime表示IPOPT_TIMESTAMP选项需要记录时间戳,ts_needaddr表示 IPOPT_TIMESTAMP选项需要记录IP地址。router_alert用于IPOPT_RA选项。Typedef struct _ipoptionhdr Unsigned char code; /报文类型 Unsigned char len; Unsigned char ptr; Unsigned long addr9; IcmpHeader;其中各字段表示意义如下。Code: 指明IP 选项类型,对于路由记录选项,它的值是7。Len: 选项头长度。Ptr: 地址指针字段,是一个基于1的指针,指向存放下一个IP地址的位置。addr9: 记录的Ip地址列表,由于IP首部中选项的空间有限,所以可以记录的Ip地址最多是9个。9.33 函数功能描述1) IntPing()函数原型:void IntPing()IntPing()函数用于初始化ping 所需的全局变量,为各个变量赋初始值。2)userHelp()函数原型:void userHelp() userHelp()函数用于显示用户帮助信息。当程序检查到参数错误或者没有必要的参数(如主机IP地址或者主机名)时,则会调用此函数显示帮助信息。3) GetArgments()函数原型:void GetArgments(int argc, char*argv)GetArgments()函数用于获取用户提交的参数。其中argc 表示获取的参数个数,argv 用于存储获取的参数,这两个形参和主函数中的形参表示的意义一样的。4)checkSum()函数原型:USHORT checkSum(USHORT *buffer,int size)checkSum()函数用于计算校验和。计算过程是首先把数据报头中的校验和字段设置为0,然后对首部中每个16bit 进行二字段进制反码求和(整个首部看成是由一串16bit的字组成),结果存在校验和字段中。 其中buffer 用于存放ICMP数据,size表示ICMP报文大小。5)FillCMPData()函数原型:void FillCMPData()FillCMPData()函数用于填充ICMP数据报中各个字段。其中icmp_data 表示ICMP数据,datasize 表示ICMP报文大小。6) reeRes()函数原型:void reeRes()reeRes()函数用于释放占用的资源,包括关闭初始化socket 调用的函数的、关闭创建的socket和释放分配的内存等。7)DecodeIPOptions()函数原型:void DecodeIPOptions()DecodeIPOptions()函数用于解读IP选项,从中读出从源主机到目的主机经过的路由,并输出路由信息。Buf表示存放接收到的ICMP报文的缓冲区,bytes表示接收到的字节数。8)DecodelICMPHeader()函数原型:void DecodelICMPHeader(char*buf,int bytes,SOCKADDR_IN*from)DecodelICMPHeader()函数用于解读ICMP报文信息。Buf表示存放接收到的ICMP报文的缓冲区,bytes表示接收到的字节数,from 表示发送ICMP回显应答的主机IP地址。9)PingTest() 函数原型:void PingTest(int timeout)PingTest()函数用于进行Ping操作。其中timeout表示设定的发送超时值。9.4 程序实现9.1.4 源码分析1. 程序预处理/*导入库文件*/#pragma comment( lib, ws2_32.lib ) /这是链接API相关连的Ws2_32.lib静态库/*加载头文件*/#include #include #include #include #include /*定义常量*/#define IP_RECORD_ROUTE 0x7 /*表示要记录路由*/#define DEF_PACKET_SIZE 32 /*默认数据报大小*/#define MAX_PACKET 1024 /*最大的ICMP数据报大小*/#define MAX_IP_HDR_SIZE 60 /*最大IP头长度*/ #define ICMP_ECHO 8 /*ICMP报文类型,回显请求*/#define ICMP_ECHOREPLY 0 /*ICMP报文类型,回显应答*/#define ICMP_MIN 8 /*最小的ICMP数据报大小*/*自定义函数原型*/void InitPing(); / IntPing()函数用于初始化ping 所需的全局变量void UserHelp();void GetArgments(int argc, char* argv); USHORT CheckSum(USHORT *buffer, int size);void FillICMPData(char *icmp_data, int datasize);void FreeRes();void DecodeIPOptions(char *buf, int bytes);void DecodeICMPHeader(char *buf, int bytes, SOCKADDR_IN* from);void PingTest(int timeout);/*IP报头字段数据结构*/typedef struct _iphdr unsigned int h_len:4; /*IP报头长度*/ unsigned int version:4; /*IP的版本号*/ unsigned char tos; /*服务的类型*/ unsigned short total_len; /*数据报总长度*/ unsigned short ident; /*惟一的标识符*/ unsigned short frag_flags; /*分段标志*/ unsigned char ttl; /*生存期*/ unsigned char proto; /*协议类型(TCP、UDP等)*/ unsigned short checksum; /*校验和*/ unsigned int sourceIP; /*源IP地址*/ unsigned int destIP; /*目的IP地址*/ IpHeader;/*ICMP报头字段数据结构*/typedef struct _icmphdr BYTE i_type; /*ICMP报文类型*/ BYTE i_code; /*该类型中的代码号*/ USHORT i_cksum; /*校验和*/ USHORT i_id; /*惟一的标识符*/ USHORT i_seq; /*序列号*/ ULONG timestamp; /*时间戳*/ IcmpHeader;/*IP选项头字段数据结构*/typedef struct _ipoptionhdr unsigned char code; /*选项类型*/ unsigned char len; /*选项头长度*/ unsigned char ptr; /*地址偏移长度*/ unsigned long addr9; /*记录的IP地址列表*/ IpOptionHeader;/*定义全局变量*/SOCKET m_socket;IpOptionHeader IpOption;SOCKADDR_IN DestAddr;SOCKADDR_IN SourceAddr;char *icmp_data;char *recvbuf;USHORT seq_no ;char *lpdest;int datasize;BOOL RecordFlag;double PacketNum;BOOL SucessFlag;2. 初始化模块/*初始化变量函数*/ void InitPing() WSADATA wsaData; icmp_data = NULL; seq_no = 0; recvbuf = NULL; RecordFlag = FALSE; lpdest = NULL; datasize = DEF_PACKET_SIZE; PacketNum = 5; SucessFlag = FALSE; /*Winsock初始化*/ if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) /*如果初始化不成功则报错,GetLastError()返回发生的错误信息*/ printf(WSAStartup() failed: %dn, GetLastError(); return ; m_socket = INVALID_SOCKET;3. 功能控制模块/*显示信息函数*/void UserHelp() printf(UserHelp: ping -r data sizen); printf( -r record routen); printf( -n record amountn); printf( host remote machine to pingn); printf( datasize can be up to 1KBn); ExitProcess(-1); /*获取ping选项函数*/void GetArgments(int argc,char* argv) int i; int j; int exp; int len; int m; /*如果没有指定目的地地址和任何选项*/ if(argc = 1) printf(nPlease specify the destination IP address and the ping option as follow!n); UserHelp(); for(i = 1; i =1;j-,exp+) /*根据argvij中的ASCII值计算要获取的记录条数(十进制数)*/ PacketNum += (double)(argvij-48)*pow(10,exp); else switch (tolower(argvi1) /*选项指示要获取路由信息*/ case r: RecordFlag = TRUE; break; /*没有按要求提供选项*/ default: UserHelp(); break; /*参数是数据报大小或者IP地址*/ else if (isdigit(argvi0) for(m=1;m 1) cksum += *buffer+; size -= sizeof(USHORT); if (size) cksum += *(UCHAR*)buffer; /*对每个16bit进行二进制反码求和*/ cksum = (cksum 16) + (cksum & 0xffff); cksum += (cksum 16); return (USHORT)(cksum);/*填充ICMP数据报字段函数*/void FillICMPData(char *icmp_data, int datasize) IcmpHeader *icmp_hdr = NULL; char *datapart = NULL; icmp_hdr = (IcmpHeader*)icmp_data; /*ICMP报文类型设置为回显请求*/ icmp_hdr-i_type = ICMP_ECHO; icmp_hdr-i_code = 0; /*获取当前进程IP作为标识符*/ icmp_hdr-i_id = (USHORT)GetCurrentProcessId(); icmp_hdr-i_cksum = 0; icmp_hdr-i_seq = 0; datapart = icmp_data + sizeof(IcmpHeader); /*以数字0填充剩余空间*/ memset(datapart,0,datasize-sizeof(IcmpHeader);/*释放资源函数*/void FreeRes() /*关闭创建的套接字*/ if (m_socket != INVALID_SOCKET) closesocket(m_socket); /*释放分配的内存*/ HeapFree(GetProcessHeap(), 0, recvbuf); HeapFree(GetProcessHeap(), 0, icmp_data); /*注销WSAStartup()调用*/ WSACleanup(); return ;4. 数据报解读模块/*解读IP选项头函数*/void DecodeIPOptions(char *buf, int bytes) IpOptionHeader *ipopt = NULL; IN_ADDR inaddr; int i; HOSTENT *host = NULL; /*获取路由信息的地址入口*/ ipopt = (IpOptionHeader *)(buf + 20); printf(RR: ); for(i = 0; i ptr / 4) - 1; i+) inaddr.S_un.S_addr = ipopt-addri; if (i != 0) printf( ); /*根据IP地址获取主机名*/ host = gethostbyaddr(char *)&inaddr.S_un.S_addr,sizeof(inaddr.S_un.S_addr), AF_INET); /*如果获取到了主机名,则输出主机名*/ if (host) printf(%-15s) %sn, inet_ntoa(inaddr), host-h_name); /*否则输出IP地址*/ else printf(%-15s)n, inet_ntoa(inaddr); return;/*解读ICMP报头函数*/void DecodeICMPHeader(char *buf, int bytes, SOCKADDR_IN *from) IpHeader *iphdr = NULL; IcmpHeader *icmphdr = NULL; unsigned short iphdrlen; DWORD tick; static int icmpcount = 0; iphdr = (IpHeader *)buf; /*计算IP报头的长度*/ iphdrlen = iphdr-h_len * 4; tick = GetTickCount(); /*如果IP报头的长度为最大长度(基本长度是20字节),则认为有IP选项,需要解读IP选项*/ if (iphdrlen = MAX_IP_HDR_SIZE) & (!icmpcount) /*解读IP选项,即路由信息*/ DecodeIPOptions(buf, bytes); /*如果读取的数据太小*/ if (bytes sin_addr); icmphdr = (IcmpHeader*)(buf + iphdrlen); /*如果收到的不是回显应答报文则报错*/ if (icmphdr-i_type != ICMP_ECHOREPLY) printf(nonecho type %d recvdn, icmphdr-i_type); return; /*核实收到的ID号和发送的是否一致*/ if (icmphdr-i_id != (USHORT)GetCurrentProcessId() printf(someone elses packet!n); return ; SucessFlag = TRUE; /*输出记录信息*/ printf(%d bytes from %s:, bytes, inet_ntoa(from-sin_addr); printf( icmp_seq = %d. , icmphdr-i_seq); printf( time: %d ms, tick - icmphdr-timestamp); printf(n); icmpcount+; return;5. Ping 测试模块/*ping函数*/void PingTest(int timeout) int ret; int readNum; int fromlen; struct hostent *hp = NULL; /*创建原始套接字,该套接字用于ICMP协议*/ m_socket = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0,WSA_FLAG_OVERLAPPED); /*如果套接字创建不成功*/ if (m_socket = INVALID_SOCKET) printf(WSASocket() failed: %dn, WSAGetLastError(); return ; /*若要求记录路由选项*/ if (RecordFlag) /*IP选项每个字段用0初始化*/ ZeroMemory(&IpOption, sizeof(IpOption); /*为每个ICMP包设置路由选项*/ IpOption.code = IP_RECORD_ROUTE; IpOption.ptr = 4; IpOption.len = 39; ret = setsockopt(m_socket, IPPROTO_IP, IP_OPTIONS,(char *)&IpOption, sizeof(IpOption); if (ret = SOCKET_ERROR) printf(setsockopt(IP_OPTIONS) failed: %dn,WSAGetLastError(); /*设置接收的超时值*/ readNum = setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO,(char*)&timeout, sizeof(timeout); if(readNum = SOCKET_ERROR) printf(setsockopt(SO_RCVTIMEO) failed: %dn,WSAGetLastError(); return ; /*设置发送的超时值*/ timeout = 1000; readNum = setsockopt(m_socket, SOL_SOCKET, SO_SNDTIMEO,(char*)&timeout, sizeof(timeout); if (readNum = SOCKET_ERROR) printf(setsockopt(SO_SNDTIMEO) failed: %dn,WSAGetLastError(); return ; /*用0初始化目的地地址*/ memset(&DestAddr, 0, sizeof(DestAddr); /*设置地址族,这里表示使用IP地址族*/ DestAddr.sin_family = AF_INET; if (DestAddr.sin_add
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年新能源汽车换电模式在共享出行领域的应用与电池资产管理策略报告
- 2025居间合同格式
- 2025年农业生物技术在种子品种培育中的基因资源利用与保护研究报告
- 2025年中国个人漂浮装置行业市场全景分析及前景机遇研判报告
- 泡桐树的特点
- 肺炎与哮喘的区别
- 《离婚协议书范本:婚姻关系解除及子女抚养权明确》
- 婚姻解除财产分割专项离婚协议书范本
- 离婚财产分割与子女抚养安排协议书示范文本
- 租赁住宅人身安全免责及安全保障条款合同
- GB/T 12643-2025机器人词汇
- GB/T 20028-2005硫化橡胶或热塑性橡胶应用阿累尼乌斯图推算寿命和最高使用温度
- GB 21258-2007常规燃煤发电机组单位产品能源消耗限额
- GA/T 1499-2018卷帘门安全性要求
- 2型糖尿病的综合管理课件
- 马克思主义政治经济学第2章-货币课件
- 学术规范与论文写作讲述课件
- 七年级数学学习·探究·诊断上册
- 弹簧设计基础知识概要课件
- GB∕T 17794-2021 柔性泡沫橡塑绝热制品
- 商业银行监管评级简表
评论
0/150
提交评论