第2章-套接字编程基础_第1页
第2章-套接字编程基础_第2页
第2章-套接字编程基础_第3页
第2章-套接字编程基础_第4页
第2章-套接字编程基础_第5页
已阅读5页,还剩67页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第2章 Socket编程接口杨 明紫金学院计算机系网络编程2022-5-31内容nWinsock网络编程接口 n面向连接的套接字编程 n无连接的套接字编程WinSock编程接口nWindows Socktes规范 nMicrosoft公司以Berkeley Sockets规范为范例,定义了Windows Socktes规范,简称Winsock规范。这是Windows操作系统环境下的套接字网络应用程序编程接口(API)。nWindows Sockets 规范是一套开放的、支持多种协议的Windows下的网络编程接口。从1991年到1995年,从1.0版发展到2.2版,已成为Windows网络编程

2、的事实上的标准。WinSock2 编程模型4 4WinSock2 编程模型5 5WINSOCK2工作模式6 6Winsock函数n初始化函数n基本的Winsock函数n数据传输函数n辅助函数n信息查询函数n错误处理函数Winsock初始化函数Winsock初始化函数n初始化函数初始化函数WSAStartup()nWinsock 应用程序要做的第一件事,就是必须首先调用WSAStartup()函数对Winsock进行初始化,成功后,才能调用其他的Winsock API函数。nWSAStartup()函数的调用格式函数的调用格式nint WSAStartup( WORD wVersionReque

3、sted, LPWSADATA lpWSAData );n用法nWSADATA WsaDatnWSAStartup(MAKEWORD(2,2), &WsaDat);Winsock初始化函数n注销函数注销函数WSACleanup()n当程序使用完Winsock.DLL提供的服务后,应用程序必须调用WSACleanup()函数,来解除与Winsock.DLL库的绑定,释放Winsock实现分配给应用程序的系统资源,中止对Windows Sockets DLL的使用。 nint WSACleanup ( void ); 基本的Winsock函数n创建套接字-socket函数n绑定套接字-bi

4、nd函数n请求连接-connect函数n监听连接-listen函数n接受连接-accept函数n断开套接字-shutdown函数n关闭套接字-closesocket函数创建套接字nsocket()nsocket过程创建一个套接字并返回一个整型描述符n格式:int SOCKET( int Protofamily, int Type, int Protocol); n参数1: 说明使用协议簇,对于IPv4,设置为AF_INETn参数2:说明套接字类型,如SOCK_STREAM,SOCK_DGRAMn参数3:采用的底层协议,设为0时为套接字服务自动选择n套接字创建成功,则返回套接字描述符,否则返回I

5、NVALID_SOKET错误nSOCKET sockfd=SOCKET( AF_INET, SOCK_STREAM, 0); /* 创建一个流式套接字。nSOCKET sockfd=SOCKET( AF_INET, SOCK_DGRAM, 0); /* 创建一个数据报套接字。 套接字绑定nbind()n多用于服务器将创建的套接字与制定的网络地址进行绑定,客户端一般不需绑定nint BIND( int Sockfd, struct sockaddr* My_addr, int Addrlen); n参数1:套接字标识符n参数2:要绑定的网络地址n参数3:网络地址结构的长度n返回值:若返回0表示正

6、确绑定,否则返回SOCKET_ERROR表示有错。套接字使用的地址数据类型nsockaddr_in结构,专门针对Internet通信域,存储套接字相关的网络地址信息,例如IP地址,传输层端口号等信息。struct sockaddr_in short int sin_family; / 地址家族unsigned short int sin_port; / 端口号struct in_addr sin_addr; / IP 地址unsigned char sin_zero8; / 全为0 SOCKET serSock; / 定义了一个SOCKET 类型的变量。sockaddr_in my_addr;

7、 / 定义一个Sockaddr_in型的结构实例变量。int err; / 出错码。 int slen=sizeof( sockaddr); / sockaddr 结构的长度。serSock = socket(AF_INET, SOCK_DGRAM,0 ); / 创建数据报套接字。memset(my_addr,0); / 将Sockaddr_in的结构实例变量清零。my_addr.sin_family = AF_INET; / 指定通信域是Internet。my_addr.sin_port = htons(21); / 指定端口,将端口号转换为网络字节顺序。 创建套接字示例/* 指定IP地址,

8、将IP地址转换为网络字节顺序。my_addr.sin_addr.s_addr = htonl( INADDR-ANY); /* 将套接字绑定到指定的网络地址,对&my_addr进行了强制类型转换。if (BIND(serSock, (LPSOCKADDR )&my_addr, slen) = SOCKET_ERROR ) /* 调用WSAGetLastError()函数,获取最近一个操作的错误代码。 err = WSAGetLastError(); /* 以下可以报错,进行错误处理。 套接字绑定示例请求连接nconnect()n仅用于客户端,用来请求建立服务器连接n格式:int

9、 connect( int sockfd, struct sockaddr * name, int namelen); n返回值:连接成功,返回0;否则返回-1nif (connect(sockfd, (struct sockaddr*)(&serv_addr),sizeof(struct sockaddr)0) 报错,并退出 请求连接n举例nstruct sockaddr_in daddr;nmemset(void *)&daddr,0,sizeof(daddr);ndaddr.sin_family=AF_INET;ndaddr.sin_port=htons(8888);nd

10、addr.sin_addr.s_addr=inet_addr(133.197.22.4);nIf (connect(ClientSocket,(struct sockaddr *)&daddr,sizeof(daddr)0) 报错,并退出 ;启动监听nlisten()n告诉服务器端套接字开始监听客户机的连接请求n格式:int listen(int Socket, int Queuesize)接受连接请求naccept()n格式:int accept( int sockfd, struct sockaddr* addr, int* addrlen);n返回值:如执行正确,返回新的套接字描

11、述符,该套接字已和请求的客户端建立连接;否则出错返回-1.n举例:nint clientfd; / 定义响应套接字描述符变量nint addrler=sizeof(sockaddr); / 获得套接字地址结构长度。nstruct sockaddr_in cltsockaddr; / 定义返回客户端地址的结构nclientfd=ACCEPT(listenfd, (sockaddr* )(&cltsockaddr), &addrlen); / 接收客户连接请求 断开与关闭套接字n断开套接字shutdown()n禁止在一个套接口上进行数据的接收与发送n格式:int shutdown(

12、 int sockfd, int how)nSD_SENDnSD_RECEIVEnSD_BOTHn关闭套接字closesocket()n关闭套接字,释放资源n格式:int closesocket( int sockfd)数据传输函数nsend()n向一个已连接的套接字发送数据n格式: int send( int sockfd, char * buf, int len, int flags);n正确返回实际发送的字节数,否则返回-1数据传输函数nrecv()n从已建立的套接字接收数据n格式: int recv( int sockfd, char * buf, int len, int flags

13、);n正确返回实际发送的字节数,否则返回-1Winsock的辅助函数nWinsock中的字节顺序转换函数中的字节顺序转换函数n两种本机字节顺序本机字节顺序和网络字节顺序n本机字节顺序n在具体计算机中的多字节数据的存储顺序n网络字节顺序n多字节数据在网络协议报头中的存储顺序n不同字节顺序的转换n应用程序在编程的时候,在把IP地址和端口号装入套接字的时候,应当把它们从本机字节顺序转换为网络字节顺序;n相反,在本机输出时,应将它们从网络字节顺序转换为本机字节顺序。 字节序转换函数nhtons() 短整数本机顺序转换为网络顺序,用于端口号。nhtonl() 长整数本机顺序转换为网络顺序,用于IP地址。

14、nntohs() 短整数网络顺序转换为本机顺序,用于端口号。nntohl() 长整数网络顺序转化为本机顺序,用于IP地址。(1)htonl() 将主机的无符号长整型数本机顺序转换为网络字节顺序 (Host to Network Long),用于IP地址。u_long PASCAL FAR htonl( u_long hostlong); hostlong是主机字节顺序表达的32位数。htonl()返回一个网络字节顺序的值。(2)htons() 将主机的无符号短整型数转换成网络字节顺序(Host to Network Short),用于端口号。u_short PASCAL FAR htons(

15、u_short hostshort);hostshort:主机字节顺序表达的16位数。htons()返回一个网络字节顺序的值。 字节序转换函数(3)ntohl()将一个无符号长整型数从网络字节顺序转换为主机字节顺序。用于IP地址。u_long PASCAL FAR ntohl( u_long netlong); netlong是一个以网络字节顺序表达的32位数,ntohl()返回一个以主机字节顺序表达的数。(4)ntohs()将一个无符号短整型数从网络字节顺序转换为主机字节顺序。用于端口号u_short PASCAL FAR ntohs( u_short netshort);netshort是

16、一个以网络字节顺序表达的16位数。ntohs()返回一个以主机字节顺序表达的数。 字节序转换函数2获取与套接口相连的端地址获取与套接口相连的端地址GETPEERNAME()int getpeername( SOCKET s, struct sockaddr * name, int * namelen); 3获取一个套接口的本地名字获取一个套接口的本地名字GETSOCKNAME()int getsockname( SOCKET s, struct sockaddr * name, int * namelen); 4将一个点分十进制形式的将一个点分十进制形式的IP地址转换成一个长整型数地址转换成一

17、个长整型数INET_ADDR()unsigned long inet_addr (const char * cp); 5 将 网 络 地 址 转 换 成 点 分 十 进 制 的 字 符 串 格 式 将 网 络 地 址 转 换 成 点 分 十 进 制 的 字 符 串 格 式INET_NTOA()char * inet_ntoa( struct in_addr in); Winsock的信息查询函数nGethostname()n用来返回本地计算机的标准主机名。nint gethostname(char* name, int namelen);nGethostbyname()n返回对应于给定主机名的

18、主机信息。nstruct hostent* gethostbyname(const char* name);nGethostbyaddr()n根据一个IP地址取回相应的主机信息。nstruct hostent* gethostbyaddr(const char* addr, int len, int type);nGetservbyname()n返回对应于给定服务名和协议名的相关服务信息。nstruct servent* getservbyname(const char* name, const char* proto);主机名解析nGethostbynamen我们使用域名来标识站点,可以将文

19、字型的主机域名直接转换成IP地址n格式:struct hostent* gethostbyname( const char* name);n入口参数:是站点的主机域名字符串,n返回值: 是指向hostent 结构的指针,失败返回NULLnhostent结构包含主机名,主机别名数组,返回地址的类型(一般是AF-INET),地址长度的字节数,已符合网络字节顺序的主机网络地址等。n将转换后的IP地址复制到服务器的地址结构中 Winsock的信息查询函数n除了Gethostname()函数以外,其它六个函数有以下共同的特点:n函数名都采用GetXbyY的形式。 n如果函数成功地执行,就返回一个指向某种

20、结构的指针,该结构包含所需要的信息。n如果函数执行发生错误,就返回一个空指针。应用程序可以立即调用WSAGetLastError()来得到一个特定的错误代码。n函数执行时,可能在本地计算机上查询,也可能通过网络向域名服务器发送请求,来获得所需要的信息,这取决于用户网络的配置方式。WINSOCK程序结构n新建一个Win32 API空项目ninclude必需的头文件n链接Winsock库文件WS2_32.libn开始Winsock应用程序编程3333#include / include必需的头文件#include #include #pragma comment(lib, Ws2_32.lib)

21、/链接Winsock库文件WS2_32.libint main() /开始Winsock应用程序编程 return 0;不同类型套接字编程n通信方式nC/S模式与P2P模式n不同连接方式n面向连接与面向无连接n阻塞方式n阻塞模式与非阻塞模式n可以进行组合形成不同类型的网络编程面向连接的套接字工作过程 面向连接客户机编程3636n面向连接客户机编程步骤(阻塞模式)(1)初始化Winsock服务(2)创建套接字(3)主机名解析,配置套接字要访问的服务器的地址结构信息(4)连接服务器(5)从服务接收信息并显示(6)断开套接字连接,不允许发送数据,但可以继续接收数据(7)关闭套接字,释放资源(8)关闭

22、Winsock服务完整的客户机程序-(1)#include #include #pragma comment(lib,ws2_32.lib)int main()WSADATA WsaDat; / 初始化 Winsock服务if(WSAStartup(MAKEWORD(2,2),&WsaDat)!=0)std:coutWinsock错误 - Winsock服务初始化失败!rn;WSACleanup();system(PAUSE);return 0;SOCKET Socket=socket(AF_INET,SOCK_STREAM,0); / 创建套接字if(Socket=INVALID_S

23、OCKET)std:cout套接字错误 -创建套接字失败!rn;WSACleanup();system(PAUSE);return 0;struct hostent *host; / 主机名解析if(host=gethostbyname(localhost)=NULL)std:couth_addr);/ 连接服务器if(connect(Socket,(SOCKADDR*)(&SockAddr),sizeof(SockAddr)!=0)std:cout与服务器连接失败!rn;WSACleanup();system(PAUSE);return 0; 完整的客户机程序-(2) / 从服务接收

24、信息并显示char buffer1024;memset(buffer,0,1023);int inDataLength=recv(Socket,buffer,1024,0);std:coutbuffer;/ 断开套接字连接,不允许发送数据,但可以继续接收数据shutdown(Socket,SD_SEND);/ 关闭套接字,释放资源closesocket(Socket);/ 关闭Winsock服务,清理内存WSACleanup();system(PAUSE);return 0;完整的客户机程序-(3)面向连接服务器编程n阻塞模式服务器编程步骤阻塞模式服务器编程步骤(1)启动并初始化Winsock

25、2服务(与客户机同)(2)创建Socket(与客户机同)(3)填充服务器地址、端口信息(有变化)(4)绑定服务器地址信息到套接字(新增步骤)(5)侦听客户连接(新增步骤)(6)接受客户连接(新增步骤)(7)向客户机发送数据(8)断开套接字连接,停止发送数据(与客户机同)(9)关闭套接字(与客户机同)(10)关闭Winsock套接字服务(与客户机同)4040完整的服务器程序-(1)#include #include #pragma comment(lib,ws2_32.lib)int main()WSADATA WsaDat;if(WSAStartup(MAKEWORD(2,2),&Ws

26、aDat)!=0)std:coutWinsock服务初始化失败!rn;WSACleanup();system(PAUSE);return 0;SOCKET Socket=socket(AF_INET,SOCK_STREAM,0);if(Socket=INVALID_SOCKET)std:cout创建套接字失败!rn;WSACleanup();system(PAUSE);return 0;SOCKADDR_IN serverInf;serverInf.sin_family=AF_INET;serverInf.sin_addr.s_addr=INADDR_ANY;serverInf.sin_por

27、t=htons(8888);if(bind(Socket,(SOCKADDR*)(&serverInf),sizeof(serverInf) =SOCKET_ERROR)std:cout不能绑定地址信息到套接字!rn;WSACleanup();system(PAUSE);return 0;listen(Socket,1);完整的服务器程序-(2)SOCKET TempSock=SOCKET_ERROR;while(TempSock=SOCKET_ERROR)std:cout服务器:正在等待来自客户机的连接.rn;TempSock=accept(Socket,NULL,NULL); So

28、cket=TempSock;std:cout服务器:有客户机连接到达!rnrn;char *szMessage=服务器说:有朋自远方来来,不亦乐乎rn;send(Socket,szMessage,strlen(szMessage),0);shutdown(Socket,SD_SEND); / 断开套接字连接,不允许发送数据closesocket(Socket); / 关闭套接字,释放资源WSACleanup(); /关闭Winsock服务,清理内存system(PAUSE);return 0;完整的服务器程序-(3) RECV()函数的两种执行方式 Winsock的I/O模式 有多个操作套接字

29、的系统调用会引起进程阻塞。有多个操作套接字的系统调用会引起进程阻塞。(1)ACCEPT()(2)READ()、RECV()和和READFORM()(3)WRITE()、SEND()和和SENDTO()(4)CONNECT()(5)SELECT()(6)CLOSESOCKET() 能引起阻塞的套接字调用 采用阻塞工作模式的单进程服务器是不能很好采用阻塞工作模式的单进程服务器是不能很好地同时为多个客户服务的。地同时为多个客户服务的。阻塞工作模式带来的问题非阻塞模式客户机编程n设置套接字阻塞模式nioctlsocket(Socket,FIONBIO,&iMode); n如果设置iMode=0

30、 ,套接字将处于阻塞模式n设置iMode=1,套接字工作于非阻塞模式。n缺省状态为阻塞模式n其他不同步骤n需要一个循环来处理数据接收过程非阻塞模式客户机编程for(;) / 主循环/ 接收服务器信息char buffer1024;memset(buffer,0,1023);int inDataLength=recv(Socket,buffer,1024,0);std:coutbuffer;int nError=WSAGetLastError();if(nError!=WSAEWOULDBLOCK&nError!=0)/ 断开套接字,只能接收不能发送shutdown(Socket,SD_

31、SEND);closesocket(Socket); / 关闭套接字break;Sleep(1000);非阻塞模式服务器编程1.初始化套接字2.创建套接字3.配置SOCKADDR_IN地址信息4.在套接字上侦听5.接受来自客户机的连接6.设置套接字工作模式nu_long iMode=1;nioctlsocket(Socket,FIONBIO,&iMode);for(;) / 主循环 char *szMessage=非阻塞服务器说:有朋自远方来来,不亦乐乎rn; send(Socket,szMessage,strlen(szMessage),0); int nError=WSAGetLa

32、stError(); if(nError!=WSAEWOULDBLOCK&nError!=0)std:coutWinsock错误码为: nErrorrn;std:cout客户机断开连接!rn;/ 断开套接字连接,不允许发送,可以接收shutdown(Socket,SD_SEND);/ 关闭套接字closesocket(Socket);break;Sleep(1000);非阻塞模式服务器编程非阻塞模式服务器完整代码#include #include #pragma comment(lib,ws2_32.lib)int main()WSADATA WsaDat;if(WSAStartup(

33、MAKEWORD(2,2),&WsaDat)!=0)std:coutWinsock服务初始化失败!rn;WSACleanup();system(PAUSE);return 0;SOCKET Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(Socket=INVALID_SOCKET)std:cout创建套接字失败!rn;WSACleanup();system(PAUSE); return 0;非阻塞模式服务器完整代码SOCKADDR_IN serverInf;serverInf.sin_family=AF_INET;serverInf.

34、sin_addr.s_addr=INADDR_ANY;serverInf.sin_port=htons(8888);if(bind(Socket,(SOCKADDR*)(&serverInf),sizeof(serverInf)=SOCKET_ERROR)std:cout套接字绑定失败!rn;WSACleanup();system(PAUSE);return 0;listen(Socket,1);SOCKET TempSock=SOCKET_ERROR;while(TempSock=SOCKET_ERROR)std:cout服务器:正在等待客户机连接.rn;TempSock=accep

35、t(Socket,NULL,NULL); 非阻塞模式服务器完整代码u_long iMode=1; / iMode!=0表示阻塞模式ioctlsocket(Socket,FIONBIO,&iMode);Socket=TempSock;std:cout服务器说:有新客户机连接到达!rnrn;for(;) / 主循环char *szMessage=非阻塞服务器说:有朋自远方来来,不亦乐乎rn;send(Socket,szMessage,strlen(szMessage),0);int nError=WSAGetLastError();if(nError!=WSAEWOULDBLOCK&

36、;nError!=0)std:coutWinsock错误码为: nErrorrn;std:cout客户机断开连接!rn;shutdown(Socket,SD_SEND); / 断开套接字closesocket(Socket); / 关闭套接字break;Sleep(1000);5454WSAStartup()函数执行失败时将返回一个Winsock错误码。WSADATA WsaDat;if(WSAStartup(MAKEWORD(2,2),&WsaDat)!=0)std:coutWinsock服务初始化失败!rn;WSACleanup();system(PAUSE);return 0;W

37、SADATA WsaDat;int nResult=WSAStartup(MAKEWORD(2,2),&WsaDat);if(nResult!=0)std:cout Winsock服务初始化失败,错误码: nResultrn;WSACleanup();system(PAUSE);return 0;套接字错误处理套接字错误处理错误处理错误处理2 2:接下来的代码是创建套接字,创建不成功怎么办?把程序2.5中的代码稍作如下修改即可捕获错误原因:SOCKET Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);If (Socket=INVALID_S

38、OCKET)int nError=WSAGetLastError();std:cout创建套接字失败,错误码:nErrorrn;WSACleanup();system(PAUSE);return 0;套接字错误处理错误处理错误处理3 3:成功创建套接字后,接下来的步骤是配置SOCKADDR_IN地址结构信息然后进行套接字绑定,绑定过程发生错误怎么办?if(bind(Socket,(SOCKADDR*)(&serverInf),sizeof(serverInf)=SOCKET_ERROR)int nError=WSAGetLastError();std:cout不能绑定地址信息到套接字,

39、错误码: nError 0 ) printf(Server: Total Bytes received: %dn, ByteReceived); else printf(Server: recvfrom() failed th error code: %dn, WSAGetLastError();客户端程序#include #include int main(int argc, char *argv)WSADATA wsaData;SOCKET SendingSocket;SOCKADDR_IN ReceiverAddr, SrcInfo;char *SendBuf = Sending all

40、 my love to you!;int Port = 5150 , BufLength = 1024,len, TotalByteSent;/ 初始化Winsock version 2.2if( WSAStartup(MAKEWORD(2,2), &wsaData) != 0)printf(Client: WSAStartup error %ldn, WSAGetLastError();WSACleanup(); / Clean upreturn -1; / Exit with error/ 创建收发UDP消息的套接字SendingSocket = socket(AF_INET, S

41、OCK_DGRAM, IPPROTO_UDP);if (SendingSocket = INVALID_SOCKET)printf(Client: Error at socket(): %ldn, WSAGetLastError();WSACleanup(); / Clean upreturn -1; / Exit with errorReceiverAddr.sin_family = AF_INET;ReceiverAddr.sin_port = htons(Port);ReceiverAddr.sin_addr.s_addr = inet_addr(127.0.0.1);/ 发送数据报pr

42、intf(Client: Sending datagrams.n);TotalByteSent = sendto(SendingSocket, SendBuf, BufLength, 0, (SOCKADDR *)&ReceiverAddr, sizeof(ReceiverAddr);printf(Client: sendto() looks OK!n);memset(&SrcInfo, 0, sizeof(SrcInfo);len = sizeof(SrcInfo);getsockname(SendingSocket, (SOCKADDR *)&SrcInfo, &a

43、mp;len);printf(Client: Sending IP(s) used: %sn, inet_ntoa(SrcInfo.sin_addr);printf(Client: Sending port used: %dn, htons(SrcInfo.sin_port);/ Some info on the sender sidegetpeername(SendingSocket, (SOCKADDR *)&ReceiverAddr, (int *)sizeof(ReceiverAddr);printf(Client: Receiving IP used: %sn, inet_n

44、toa(ReceiverAddr.sin_addr);printf(Client: Receiving port used: %dn, htons(ReceiverAddr.sin_port);/ When your application is finished receiving datagrams close the socket.if (closesocket(SendingSocket) != 0) printf(Client: closesocket() failed! Error code: %ldn, WSAGetLastError(); / When your applica

45、tion is finished call WSACleanup.if(WSACleanup() != 0) printf(Client: WSACleanup() failed! Error code: %ldn, WSAGetLastError(); system(pause); return 0;服务器端程序#include #include int main(int argc, char *argv)WSADATAwsaData; SOCKET ReceivingSocket;SOCKADDR_INReceiverAddr, SenderAddr;intPort = 5150, Buf

46、Length = 1024;charReceiveBuf1024;intSenderAddrSize = sizeof(SenderAddr), ByteReceived = 5; if( WSAStartup(MAKEWORD(2,2), &wsaData) != 0) printf(Server: WSAStartup failed error %ldn, WSAGetLastError(); return -1; ReceivingSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (ReceivingSocket = INVALID_SOCKET)printf(Server: Error at socket():

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论