网络编程基础(免费)

网络编程基础(免费)

ID:1308941

大小:87.50 KB

页数:21页

时间:2017-11-10

上传者:xinshengwencai
网络编程基础(免费)_第1页
网络编程基础(免费)_第2页
网络编程基础(免费)_第3页
网络编程基础(免费)_第4页
网络编程基础(免费)_第5页
资源描述:

《网络编程基础(免费)》由会员上传分享,免费在线阅读,更多相关内容在教育资源-天天文库

网络和编程基本知识   第一节了解Windows机制Windows是一个“基于事件的,消息驱动的”操作系统。在Windows下执行一个程序,只要用户进行了影响窗口的动作...   第一节了解Windows机制  Windows是一个“基于事件的,消息驱动的”操作系统。  在Windows下执行一个程序,只要用户进行了影响窗口的动作(如改变窗口大小或移动、单击鼠标等)该动作就会触发一个相应的“事件”  系统每次检测到一个事件时,就会给程序发送一个“消息”,从而使程序可以处理该事件。  每个Windows应用程序都是基于事件和消息的,而且包含一个主事件循环,它不停地、反复地检测是否有用户事件发生。每次检测到一个用户事件,程序就对该事件做出响应,处理完再等待下一个事件的发生。  Windows下的应用程序不断地重复这一过程,直至用户终止程序,用代码来描述实际上也就是一个消息处理过程的while循环语句。  下面便简单介绍一下与Windows系统密切相关的几个基本概念:  1:窗口:这是我要说的第一个概念。窗口是Windows本身以及Windows环境下的应用程序的基本界面单位,但是很多人都误以为只有具有  标题栏、状态栏、最大化、最小化按钮这样标准的方框才叫窗口。其实窗口的概念很广,例如按钮和对话框等也是窗口,只不过是一种特殊化窗口罢了。  从用户的角度看,窗口就是显示在屏幕上的一个矩形区域,其外观独立于应用程序,事实上它就是生成该窗口的应用程序与用户间的直观接口;从应用程序的角度看,窗口是受其控制的一部分矩形屏幕区。应用程序生成并控制与窗口有关的一切内容,包括窗口的大小、风格、位置以及窗口内显示的内容等。用户打开一个应用程序后,程序将创建一个窗口,并在那里默默地等待用户的要求。每当用户选择窗口中的选项,程序即对此做出响应。  2:程序:通常说的程序都是指一个能让计算机识别的文件,接触得最多的便是.exe型的可执行文件.  3:进程:说到进程,学过《操作系统》的人都很清楚,所谓进程就是应用程序的执行实例(或称一个执行程序)需要注意的是:进程是程序动态的描述,而上面说到的程序是静态的描述,两者有本质的区别。举个例子,从网上 Down了一个瑞星杀毒软件到C盘但没有运行,那个.exe可执行文件叫做程序,它是一个二进制码的文件。一旦双击了exe文件图标运行程序,那个“正在运行着的瑞星杀毒”便称为进程,它在双击的那一刻被系统创建,当你关机或者在任务栏的图标上单击鼠标右键选“退出”时,进程便消亡,彻底结束了生命。进程经历了由“创建”到“消亡”的生命期,而程序自始至终存在于你的硬盘上,不管你的机器是否启动。  4:线程:线程是进程中的一个执行单元,同一个进程中的各个线程对应于一组CPU指令、一组CPU寄存器以及一堆栈。进程本来就具有动态的含义,然而实质上是通过线程来执行体现的,从这个意义上说,Windows中进程的动态性意义已经不是很明显了,只算是给程序所占的资源划定一个范围而已,真正具有动态性意义的是线程。  5:消息:我们几乎做每一个动作都会产生一个消息,鼠标被移动会产生WM_MOUSEMOVE消息,鼠标左键被按下会产生WM_LBUTTONDOWN的消息,鼠标右键按下便产生WM_RBUTTONDOWN消息等等。所有的这些都可以通过GetMessage,SendMessage等函数得到.  6:事件:如在程序运行的过程中改变窗口的大小或者移动窗口等,都会触发相应的“事件”。  7:句柄:单单一个“柄”字便可以解释它的意思了,我们天气热摇扇子的时候只要抓住扇柄便可以控制整个扇子的运动了,在程序中也差不多是这个意思。通常一个句柄就可以传递我们所要做的事情。有经验的成员肯定清楚,编写程序总是要和各种句柄打交道的,句柄是系统用来标识不同对象类型的工具,如窗口、菜单等,这些东西在系统中被视为不同类型的对象,用不同的句柄将他们区分开来。  C++教材中给句柄下的定义是:“在Win32里,句柄是指向一个无值型对象(void*)的指针,是一个4字节长的数据”。从结构上看,句柄的确是一个指针,尽管它没有指向用于存储某个对象的内存位置,而实际上在编程时,只要抓住了对象的句柄就可以对该对象进行操作了.  8:API与SDK:API是英文ApplicationProgrammingInterface的简称,意为“应用程序接口”,泛指系统为应用程序提供的一系列接口函数。其实质是程序内的一套函数调用,在编程的时候可以直接调用,而不必知道其内部实现的过程,只知道它的原型和返回值就可了.  SDK是英文SoftwareDevelopmentKit的缩写,指“软件开发工具包”,在防火墙的设计中就经常涉及到SDK。  第二节WinAPI编程简介  下面介绍一下WINAPI.  我们需要自己编写一个工具时,必然会用到很多操作windows和控制windows的函数,这些函数就是windowsAPI.   API是ApplicationProgammingInterface的缩写.就是说API是一系列已经定义的在windows内部的函数,是应用程序和系统之间的桥梁,应用程序通过调用API来请求系统完成一系列的任务.窗口,菜单,文件操作等都是通过API实现的.  WIN32API就是WINDOWS32位平台的应用程序接口.现在可视化编程工具提供了大量控件,他们代替了API的功能.这些控件都是构建在WIN32API之上的.是封装了的API函数集合.但是对于比较复杂和特殊功能(想我们的黑客编程)来说,就必须用API函数来实现.  WINAPI存放在动态链接库(DLL)中,在98系统中,有32位的GDI32.DLL,KERNEL32.DLL,16位的GDI.EXE,KRNL386.EXE.API就存放在这些动态链接库中.  木马和后门其实就是使用了文件操作函数,这里做简要介绍:  删除文件:BOOLDeleteFile(LPCTSHlpFileName)  复制文件:BOOLCopyFile()  移动文件:BOOLMoveFile()等等  具体的API可以上网自己去查看,有很多介绍API的书籍.  第三节Windows网络协议  首先介绍一下网络协议:网络协议是网络上所有设备之间通信规则的集合,他定义了通信时信息必须采用的格式和这些格式的意义.大多数网络协议都采用分层体系结,每一层都建立在他的下层之上,向他的上一层提供服务,而把如何实现这一服务的细节对上层加以屏蔽.一台设备上的第N层与另一台设备上的第N层进行通信的规则就是第N曾协议.在网络上的个层之间中存在着许多协议,接受方和发送方同层的协议必须一致,  否则,一方就无法识别另一方发出的信息.网络协议使网络上的设备各种设备能相互交换信息.  常用的协议有:TCP/IP协议,IPX/SPX歇息等等.在局域网中常用的IPX/SPX协议.而访问INTERNET,就必须添加TCP/IP协议.  TCP/IP协议是传输控制协议/互联网络协议.他规范了网络上所有设备的通信,尤其是一个主机与另一个主机之间的数据往来格式以及传送  方式.  在网络的各层中还存在着许多协议,下面列出部分网络协议规范:  ARP地址解析协议   SNMP网络管理协议  BOOTP让无盘站从一个中心服务器上获得IP地址  DHCP动态主机配置协议  下面介绍网络7层协议在WINDOWS的实现:  7层协议WIN系统  ________________________________________  7应用层7应用程序  ________________________________________________  6表示层6WINSOCKAPI(DLL)  ___________________________________________  5会话层5SPI(DLL)  __________________________________________________  4传输层4TDI(VXD,SYS)  ___________________________________________________  3网络层3NDIS(VXD,SYS)  __________________________________________________  2数据链路层2网卡驱动程序(VXD,SYS)  ___________________________________________  1物理层1网卡  _________________________________________________  相信这个映射图可以让大家比较清楚了解他们的对应关系  TCP协议图示   应用程序协议HTTPFTPTELNET  传输协议TCPUDP  网际协议IP  物理层协议网卡  IP协议保证数据的传输,TCP协议保证数据传输的质量.  TCP/IP协议基于四层结构:应用层,传输层,网络层,接口层,数据在传输时每通过一层就要在数据上加个头,其中的数据供接受端同层使用,在接收端,每经过一层就把头去掉,来保证传输数据格式的一致.  TCP头部结构:  16位源端口号16位目的端口号  32位序列号  32位确认号  4位首部长度+6位保留字6位标志16位窗口大小  16位效验和16位紧急数据偏移量  数据段  IP头部结构:  4位IP版本号4位首部长度8位服务类型16位总长度16位标示3位标志和偏移  8位生存时间8位协议16位IP首部效验和  32位源IP地址  32位目的IP地址  TCP头和数据  第四节关于服务器和客户端编程   在网络编程中,最常用和最基础的就是WINSOCK.现在我们讨论WINDOWS下的SOCKET编程.  大凡在WIN32平台上的WINSOCK编程都要经过下列步骤:  定义变量->获得WINDOCK版本->加载WINSOCK库->初始化->创建套接字->设置套接字选项->关闭套接字>卸载WINSOCK库->释放资源  下面介绍WINSOCKC/S的建立过程:  服务器客户端  ________________________________________________  1初始化WSA1初始化WSA  ____________________________________________________  2建立一个SOCKET2建立一个SOCKET  _____________________________________________________  3绑定SOCKET3连接到服务器  _____________________________________________________  4在指定的端口监听4发送和接受数据  _____________________________________________________  5接受一个连接5断开连接  ______________________________________________________-  6发送和接受数据  ___________________________________________________  7断开连接  __________________________________________________  大家注意,在VC中进行WINSOCK编程时,需要引入如下两个库文件:WINSOCK.H(这个是WINSOCKAPI的头文件,WIN2K以上支持WINSOCK2,所以   可以用WINSOCK2.H);Ws2_32.lib(WINSOCKAPI连接库文件).  使用方式如下:  #include  #pragmacomment(lib,"ws2_32.lib")  下面我们通过具体的代码演示服务器和客户端的工作流程:  首先,建立一个WSADATA结构,通常用wsaData  WSADATAwsaData;  然后,调用WSAStartup函数,这个函数是连接应用程序与winsock.dll的第一个调用.其中,第一个参数是WINSOCK版本号,第二个参数是指向  WSADATA的指针.该函数返回一个INT型值,通过检查这个值来确定初始化是否成功.调用格式如下:WSAStartup(MAKEWORD(2,2),&wsaData),其中  MAKEWORD(2,2)表示使用WINSOCK2版本.wsaData用来存储系统传回的关于WINSOCK的资料.  if(iResuit=WSAStartup(MAKEWORD(2,2),&wsaData)!=0)  {  printf("WSAStartupfailed:%d",GetLastError());//返回值不等与0,说明初始化失败  ExitProcess();/本篇文章来源于黑客基地-全球最大的中文黑客站原文链接:http://www.hackbase.com/tech/2009-06-18/53317_4.html网络和黑客编程基本知识(5)2009-06-1809:54:18www.hackbase.com来源:互联网  网络和黑客编程基本知识 第一节了解Windows机制Windows是一个“基于事件的,消息驱动的”操作系统。在Windows下执行一个程序,只要用户进行了影响窗口的动作...//退出程序  }  应用程序在完成对请求的SOCKET库使用后,要调用WSACleanup函数来接触SOCKET库的绑定,并且释放资源.   注意WSAStartup初始化后,必须建立一个SOCKET结构来保存SOCKET句柄.  下面我们建立一个SOCKET.  首先我们建立一个m_socket的SOCKET句柄,接着调用socket()函数,函数返回值保存在m_socket中.我们使用AF_INFE,SOCK_STREAM,IPPROTO_TCP  三个参数.第一个表示地址族,AF_INFE表示TCP/IP族,第二个表示服务类型,在WINSOCK2中,SOCKET支持以下三种类型;  SOCK_STREAM流式套接字  SOCK_DGRAM数据报套接字  SOCK_RAW原始套接字  第三个参数表示协议:  IPPROTO_UDPUDP协议用于无连接数据报套接字  IPPROTO_TCPTCP协议用于流式套接字  IPPROTO_ICMPICMP协议用于原始套接字  m_socket=socket(AF_INFE,SOCK_STREAM,IPPROTO_TCP);//创建TCP协议  以下代码用于检查返回值是否有错误:  if(m_scoket==INVALID_SOCKET)  {  prinrf("Erroratsocket():%d ",GetLastError());  WSACleanup();//释放资源  return;  }  说明,如果socket()调用失败,他将返回INVALID_SOCKET.   为了服务器能接受一个连接,他必须绑定一个网络地址,下面的代码展示如何绑定一个已经初始化的IP和端口的Socket.客户端程序用这个  IP地址和端口来连接服务器.  sockaddr_inservice;  service.sin_family=AF_INET;//INTERNET地址族  service.sin_addr.s_addr=inet_addr("127.0.0.1");//将要绑定的本地IP地址  service.sin_port=htons(27015);//27015将要绑定的端口  下面我们调用BIND函数,把SOCKET和SOCKADDR以参数的形式传入,并检查错误.  if(bind(m_socket,(SOCKADDR*)&SERVICE,sizeof(service))==SOCKET_ERROR)  {  printf("bind()failed. ");  closesocket(m_socket);  return;  }  当绑定完成后,服务器必须建立一个监听队列,以接受客户端的请求.listen()使服务器进入监听状态,该函数调用成功返回0,否则返回  SOCKET_ERROR.代码如下:  if(listen(m_socket,1)==SOCKET-ERROR)  {  printf("errorlisteningonsocket. ");  }  服务器端调用完LISTEN()后,如果此时客户端调用CONNECT()函数,服务器端必须在调用ACCEPT().这样服务器和客户端才算正式完成通信程序的  连接动作.   一旦服务器开始监听,我们就要指定一个句柄来表示利用ACCEPT()函数接受的连接,这个句柄是用来发送和接受数据的表示.建立一个SOCKET句柄  SocketAcceptSocket然后利用无限循环来检测是否有连接传入.一但有连接请求,ACCEPT()函数就会被调用,并且返回这次连接的句柄.  printf("waitongforaclienttoconnect... ");  while(1)  {  AcceptSocket=SOCKET_ERROR;  while(AcceptSocket==SOCKET_ERROR)  {  AcceptSocket=accept(m_socket,NULL,NULL);  }  }  下面看客户端端代码:  sockaddr_inclientService;  clientService.sin_family=AF_INET;本篇文章来源于黑客基地-全球最大的中文黑客站原文链接:http://www.hackbase.com/tech/2009-06-18/53317_5.html网络和黑客编程基本知识(6)2009-06-1809:54:18www.hackbase.com来源:互联网  网络和黑客编程基本知识 第一节了解Windows机制Windows是一个“基于事件的,消息驱动的”操作系统。在Windows下执行一个程序,只要用户进行了影响窗口的动作...;//INTERNET地址族  clientService.sin_addr.s_addr=inet_addr("127.0.0.1");//将要绑定的本地IP地址  clientService.sin_port=htons(27015);//27015将要绑定的端口  下面调用CONNECT()函数:   if(connect(m_socket,(SOCKADDR*)&clientService,sizeof(clientService))==SOCKET_ERROR)  {  printf("Failedtoconnect. ");  WSACleanup();  return;  }//如果调用失败清理退出  //调用成功继续读写数据    到这里,服务器和客户端的基本流程介绍完毕,下面我们介绍数据交换.  send():  intsend  {  SOCKETs,//指定发送端套接字  constcharFAR?*buf,//指明一个存放应用程序要发送的数据的缓冲区  intlen,//实际要发送的数据字节数  intflags//一般设置为0  };  C/S都用SEND函数向TCP连接的另一端发送数据.  recv():  intrecv  {   SOCKETs,//指定发送端套接字  charFAR?*buf,//指明一个缓冲区存放RECC受到的数据  intlen,//指明BUF的长度  intflags//一般设置为0  };  C/S都使用RECV函数从TCP连接的另一端接受数据    首先看客户端的代码:  #include  #include  #pragmacomment(lib,"ws2_32.lib")  voidmain(){  //初始化Winsock.  WSADATAwsaData;  intiResult=WSAStartup(MAKEWORD(2,2),&wsaData);  if(iResult!=NO_ERROR)  printf("ErroratWSAStartup() ");  //建立socketsocket.  SOCKETclient;  client=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);  if(client==INVALID_SOCKET){  printf("Erroratsocket():%ld ",WSAGetLastError());  WSACleanup();   return;  }  //连接到服务器.  sockaddr_inclientService;  clientService.sin_family=AF_INET本篇文章来源于黑客基地-全球最大的中文黑客站原文链接:http://www.hackbase.com/tech/2009-06-18/53317_6.html网络和黑客编程基本知识(7)2009-06-1809:54:18  www.hackbase.com  来源:互联网  网络和黑客编程基本知识 第一节了解Windows机制Windows是一个“基于事件的,消息驱动的”操作系统。在Windows下执行一个程序,只要用户进行了影响窗口的动作...;  clientService.sin_addr.s_addr=inet_addr("127.0.0.1");  clientService.sin_port=htons(27015);  if(connect(client,(SOCKADDR*)&clientService,sizeof(clientService))==SOCKET_ERROR){  printf("Failedtoconnect. ");  WSACleanup();  return;  }  //发送并接收数据.  intbytesSent;   intbytesRecv=SOCKET_ERROR;  charsendbuf[32]="Client:Sendingdata.";  charrecvbuf[32]="";  bytesSent=send(client,sendbuf,strlen(sendbuf),0);  printf("BytesSent:%ld ",bytesSent);  while(bytesRecv==SOCKET_ERROR){  bytesRecv=recv(client,recvbuf,32,0);  if(bytesRecv==0||bytesRecv==WSAECONNRESET){  printf("ConnectionClosed. ");  break;  }  if(bytesRecv<0)  return;  printf("BytesRecv:%ld ",bytesRecv);  }  return;  }  下面是服务器端代码:  #include  #include  #pragmacomment(lib,"ws2_32.lib")   voidmain(){  //初始化  WSADATAwsaData;  intiResult=WSAStartup(MAKEWORD(2,2),&wsaData);  if(iResult!=NO_ERROR)  printf("ErroratWSAStartup() ");  //建立socket  SOCKETserver;  server=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);  if(server==INVALID_SOCKET){  printf("Erroratsocket():%ld ",WSAGetLastError());  WSACleanup();  return;  }  //绑定socket  sockaddr_inservice;  service.sin_family=AF_INET;  service.sin_addr.s_addr=inet_addr("127.0.0.1");  service.sin_port=htons(27015);  if(bind(server,(SOCKADDR*)&service,sizeof(service))==SOCKET_ERROR){  printf("bind()failed. ");   closesocket(server);  return;  }  //监听socket  if(listen(server,1)==SOCKET_ERROR)  printf("Errorlisteningonsocket. ");  //接受连接  SOCKETAcceptSocket;  printf("Waitingforaclienttoconnect... ");  while(1){  AcceptSocket=SOCKET_ERROR;  while(AcceptSocket==SOCKET_ERROR){  AcceptSocket=accept(server,NULL,NULL);  }  printf("ClientConnected. ");  server=AcceptSocket;  break;  }  //发送接受数据  intbytesSent;  intbytesRecv=SOCKET_ERROR;   charsendbuf[32]="Server:SendingData.";  charrecvbuf[32]="";  bytesRecv=recv(server,recvbuf,32,0);  printf("BytesRecv:%ld ",bytesRecv);  bytesSent=send(server,sendbuf,strlen(sendbuf),0);  printf("BytesSent:%ld ",bytesSent);  return;  }  本程序仅仅描述了同步的情况!  第五节多线程编程介绍  对于多线程的基本概念,我不在赘述,是个只要学习过一门编程语言就应该多进程和线程有个基本的了解.这里重点介绍一下如何实现多线程.  通常一个程序的主线程有操作系统创建,如果想让其创建额外的线程,可以调用CreateThread()函数来完成.函数原形如下:网络和黑客编程基本知识(8)2009-06-1809:54:18www.hackbase.com来源:互联网  网络和黑客编程基本知识 第一节了解Windows机制Windows是一个“基于事件的,消息驱动的”操作系统。在Windows下执行一个程序,只要用户进行了影响窗口的动作...  HANDLECreateThread()  {  LPSECURITY_ATTRIBUTESLPThreadAttributes,//指向SECURITY_ATTRIBUTES的指针  SIZE_TdwStackSize,//表示线程为自己所用堆栈分配的地址空间的大小系统缺省值为0  LPTHREAD_START-TOUTINElpStartAddress,//表示新线程开始执行时代码所在函数的地址即线程函数名   LPVOIDlpParameter,//是传入线程函数的参数  DWORDdwCreationFlags,//指定控制线程创建的附加标志取0线程立即执行取CREATE_SUSPENDED线程挂起  LPDWORDlpThreadld//是个DWORD类型的地址,返回赋给该新线程的ID  }  线程函数lpParameter必须有以下原形:  DWORDWINAPIXXXThreadFun(LPVOIDlpParameter)  {  return(0);  }__________________________________________________  下面我们来创建一个线程:  #include  #include  DWORDWINAPIThreadFunc(LPVOIDlpParam)//线程函数,跟普通的函数没什么两样  {  printf("Parameter=%d.",*(DWORD*)lpParam);  return0;  }  VOIDmain(VOID)  {  DWORDdwThreadId,dwThrdParam=1;   HANDLEhThread;  hThread=CreateThread(NULL,0,ThreadFunc,&dwThrdParam,0,&dwThreadId);  if(hThread==NULL)  {  printf("CreateThreadfailed(%d) ",GetLastError());  }  else  {  _getch();  CloseHandle(hThread);  }  }  关于线程同步的问题,这里就不再讲解,请大家自己查阅资料,不查阅以后可能会有困难啊.培养一下各位的自己动手能力.本篇文章来源于黑客基地-全球最大的中文黑客站原文链接:http://www.hackbase.com/tech/2009-06-18/53317_8.html网络和黑客编程基本知识(8)2009-06-1809:54:18www.hackbase.com来源:互联网  网络和黑客编程基本知识 第一节了解Windows机制Windows是一个“基于事件的,消息驱动的”操作系统。在Windows下执行一个程序,只要用户进行了影响窗口的动作...  HANDLECreateThread()  {  LPSECURITY_ATTRIBUTESLPThreadAttributes,//指向SECURITY_ATTRIBUTES的指针  SIZE_TdwStackSize,//表示线程为自己所用堆栈分配的地址空间的大小系统缺省值为0   LPTHREAD_START-TOUTINElpStartAddress,//表示新线程开始执行时代码所在函数的地址即线程函数名  LPVOIDlpParameter,//是传入线程函数的参数  DWORDdwCreationFlags,//指定控制线程创建的附加标志取0线程立即执行取CREATE_SUSPENDED线程挂起  LPDWORDlpThreadld//是个DWORD类型的地址,返回赋给该新线程的ID  }  线程函数lpParameter必须有以下原形:  DWORDWINAPIXXXThreadFun(LPVOIDlpParameter)  {  return(0);  }__________________________________________________  下面我们来创建一个线程:  #include  #include  DWORDWINAPIThreadFunc(LPVOIDlpParam)//线程函数,跟普通的函数没什么两样  {  printf("Parameter=%d.",*(DWORD*)lpParam);  return0;  }  VOIDmain(VOID)   {  DWORDdwThreadId,dwThrdParam=1;  HANDLEhThread;  hThread=CreateThread(NULL,0,ThreadFunc,&dwThrdParam,0,&dwThreadId);  if(hThread==NULL)  {  printf("CreateThreadfailed(%d) ",GetLastError());  }  else  {  _getch();  CloseHandle(hThread);  }  }  关于线程同步的问题,这里就不再讲解,请大家自己查阅资料,不查阅以后可能会有困难啊.培养一下各位的自己动手能力.本篇文章来源于黑客基地-全球最大的中文黑客站原文链接:http://www.hackbase.com/tech/2009-06-18/53317_8.html

当前文档最多预览五页,下载文档查看全文

此文档下载收益归作者所有

当前文档最多预览五页,下载文档查看全文
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,天天文库负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。
关闭