linux操作系统及程序设计5_第1页
linux操作系统及程序设计5_第2页
linux操作系统及程序设计5_第3页
linux操作系统及程序设计5_第4页
linux操作系统及程序设计5_第5页
已阅读5页,还剩93页未读 继续免费阅读

下载本文档

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

文档简介

第5讲Socket网络编程12目录网络编程协议基础Socket基本编程技术Socket高级编程技术OSI模型与TCP/IP协议栈网络编程协议基础3OSI七层协议功能物理层面向物理传输媒体,屏蔽媒体的不同链路层面向一条链路,成帧和无差错传输网络层分配地址、面向多条链路、路由和流量控制传输层面向两台主机通信,处理可靠传输细节,无差错、无失序传输会话层面向一次会话,协调双方的交互、同步表示层面向通信内容的表示,大家认同的描述方式应用层面向建立在通信基础上的应用,为应用提供通信服务网络编程协议基础4TCP协议特点面向连接的可靠传输端到端、建立/断开连接正确、顺序传送数据协议关注问题IP数据报的丢失、重复、失序、延迟发送和接收速度的匹配系统重启动,一方连接信息丢失网络拥塞网络编程协议基础5UDP协议特点无连接不需要在通信前建立连接不使用控制报文传输开销低面向报文不将报文分割,也不合并UDP报文大小直接影响网络利用率过小造成报头比率过大过大造成MTU分片尽力而为、任意交互一对一、一对多、多对一和多对多网络编程协议基础6网络服务的标识TCP/UDP端口号作为服务器程序标识服务器启动时,首先在本地主机注册所使用的TCP/UDP端口号客户通过与服务器指定的TCP端口建立连接(或直接向服务器指定的UDP端口发送信息)来访问特定服务运行服务器程序的主机收到信息后,将其转交给注册该端口的服务器程序处理网络编程协议基础7客户/服务器交互模型服务器程序被动等待请求并做出响应客户程序主动向服务器发出服务请求网络编程协议基础8客户/服务器程序特性对比网络编程协议基础9服务器请求处理流程—循环服务器方案系统资源要求不高在处理一个请求时其他请求必须等待主要针对于面向无连接的客户/服务器模型网络编程协议基础10服务器请求处理流程—并发服务器方案系统资源要求较高实时性和灵活性是该方案的最大特点主要针对于面向连接的客户/服务器模型网络编程协议基础11Linux的网络分层结构BSDSocket是通用接口,支持各种网络工作形式INETSocket支持包括TCP/IP协议在内的Internet地址族网络应用BSDSocket层INETSocket层TCPUDPIPPPPSLIPSocketARP用户数据界面接口界面协议分层网络驱动网络编程协议基础12目录网络通信协议基础Socket基本编程技术Socket高级编程技术13socket基本概念Socket接口是应用程序与TCP/IP协议栈的接口定义一组函数/例程,支持TCP/IP网络应用程序开发与数据通信相关的系统调用是read()/write()是一种文件描述符一个套接字描述一个通信连接的一端两个通信程序中各自有一个套接字来描述自己的Socket不是TCP/IP标准的组成部分,但已成为事实上的工业标准UNIX系列系统提供SocketWindows系列、Macintosh系列、Solaris等亦提供网络编程协议基础14Socket端到端通信的形式形式(IP,PORT)网络进程标识<协议,本地地址,本地端口>网间通信标识<协议,本地地址,本地端口,远程地址,远程端口>端口分类公认端口小于256的端口作为保留端口注册端口动态和/或私有端口Socket基本编程技术15基本socketAPIsocket()创建一个新的Socketclose()关闭一个Socketbind()将服务器(IP,Port)赋予Socketlisten()等待到来的客户连接请求(TCP)accept()接受客户连接请求并建立连接(TCP)connect()向服务器发出连接请求send()/recv()发送/接收数据Socket基本编程技术16字节顺序字节顺序大端模式(big

endian):高字节放到高地址上小端模式(little

endian):高字节放到低地址上主机字节顺序(HBO,HostByteOrder)不同的机器HBO不相同,与CPU设计有关Motorola68k系列,HBO与NBO相同Intelx86系列,HBO与NBO相反网络字节顺序(NBO,NetworkByteOrder)使用统一的字节顺序,避免兼容性问题解决兼容性问题途径往网络上发送前:转换成网络字节序从网络接收数据:转换成主机字节序

Socket基本编程技术17字节顺序转换函数头文件#include<netinet/in.h>函数原型uint32_thtonl(uint32_thostlong);把32位值从主机字节序转换成网络字节序uint16_thtons(uint16_thostshort);把16位值从主机字节序转换成网络字节序uint32_tntohl(uint32_thostlong);把32位值从网络字节序转换成主机字节序uint16_tntohs(uint16_thostshort);把16位值从网络字节序转换成主机字节序说明h代表host,n代表networks代表short,l代表longSocket基本编程技术18socket()函数功能创建一个套接字#include<sys/socket.h>函数原型intsocket(intdomain,inttype,intprotocol);参数说明domain:通信协议族,即地址族type:套接字类型protocol:通信协议常设置为0,由内核根据指定的类型和协议族使用默认的协议返回值成功时,返回一个大于等于0的文件描述符失败时,返回一个小于0的值Socket基本编程技术19Linux支持的协议和地址族Socket基本编程技术20套接字类型流套接字(SOCK_STREAM)可靠的、面向连接的通信使用TCP协议数据报套接字(SOCK_DGRAM)无连接服务使用UDP协议原始套接字(SOCK_RAW)允许对底层协议(如IP、ICMP)直接访问Socket基本编程技术21socket()函数代码框架intmain(){

……

intsockfd;

if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1){

perror(“socket”);

exit(1);

}

……}Socket基本编程技术22套接字选项函数原型int

getsockopt(int

sockfd,int

level,int

optname,void

*optval,socklen_t

*optlen)int

setsockopt(int

sockfd,int

level,int

optname,const

void

*optval,socklen_t

*optlen)功能控制套接字行为,如修改缓冲区大小、传输方式等参数说明level:指定控制套接字的层次SOL_SOCKET:通用套接字选项IPPROTO_IP:IP选项IPPROTO_TCP:TCP选项

optname:指定控制方式(选项名称)optval:获得/设置套接字选项值Socket基本编程技术23

SOL_SOCKET参数选项 SO_BROADCAST 允许发送广播数据

int

SO_DEBUG

允许调试

int

SO_DONTROUTE

不查找路由

int

SO_ERROR

获得套接字错误

int

SO_KEEPALIVE

保持连接

int

SO_LINGER

延迟关闭连接

struct

linger

SO_OOBINLINE

带外数据放入正常数据流

int

SO_RCVBUF

接收缓冲区大小

int

SO_SNDBUF

发送缓冲区大小

int

SO_RCVLOWAT

接收缓冲区下限

int

SO_SNDLOWAT

发送缓冲区下限

int

SO_RCVTIMEO

接收超时

struct

timeval

SO_SNDTIMEO

发送超时

struct

timeval

SO_REUSERADDR

允许重用本地地址和端口

int

SO_TYPE

获得套接字类型

int

SO_BSDCOMPAT

与BSD系统兼容

int

Socket基本编程技术24IPPROTO_IP与IPPRO_TCP参数选项IPPROTO_IPIP_HDRINCL在数据包中包含IP首部IP_OPTINOSIP首部选项IP_TOS服务类型IP_TTL生存时间IPPRO_TCPTCP_MAXSEGTCP最大数据段的大小TCP_NODELAY不使用Nagle算法

Socket基本编程技术25套接字选项示例更改发送/接收缓冲区大小接收缓冲区

intnRecvBuf=32*1024;

//设置为32K

setsockopt(s,SOL_SOCKET,SO_RCVBUF,(constchar*)&nRecvBuf,sizeof(int));发送缓冲区

intnSendBuf=32*1024;//设置为32K

setsockopt(s,SOL_SOCKET,SO_SNDBUF,(constchar*)&nSendBuf,sizeof(int));说明对于客户,SO_RCVBUF选项必须在connect之前设置对于服务器,SO_RCVBUF选项必须在listen前设置Socket基本编程技术26bind()函数功能将套接字地址与所创建的套接字号联系起来客户端如果只想使用connect(),则无须使用该函数#include<sys/socket.h>函数原型intbind(intsockfd,structsockaddr*my_addr,socklen_taddrlen);参数说明sockfd:调用socket返回的文件描述符my_addr:保存地址信息(IP地址和端口)addrlen:设置为sizeof(structsockaddr)返回值成功时,返回0失败时,返回-1Socket基本编程技术27sockaddr结构定义功能保存socket信息结构structsockaddr{unsignedshortsa_family;/*地址族,AF_xxx*/

charsa_data[14];/*协议地址*/};说明sa_family一般为AF_INET(表示TCP/IP)sa_data包含socket的IP地址和端口号/include/linux/socket.hSocket基本编程技术28sockaddr_in结构定义功能sockaddr的另一种表示形式结构structsockaddr_in{

shortintsin_family;/*地址族*/

unsignedshortintsin_port;/*端口号*/

structin_addrsin_addr;/*IP地址*/

unsignedcharsin_zero[8];/*填充0,保持与structsockaddr等长*/};说明sin_zero用于将sockaddr_in结构填充到与structsockaddr等长,可用bzero()或memset()函数将其置为0当sin_port=0时,系统随机选择一个未被使用的端口号当sin_addr=INADDR_ANY时,表示填入本机IP地址指向sockaddr_in的指针和指向sockaddr的指针可相互转换structin_addr{__u32s_addr;};Socket基本编程技术29bind()函数示例 #include<string.h>

#include<sys/types.h>

#include<sys/socket.h>

#defineMYPORT3490

intmain(){

intsockfd;

structsockaddr_inmy_addr;

sockfd=socket(AF_INET,SOCK_STREAM,0);

my_addr.sin_family

=AF_INET;

my_addr.sin_port=htons(MYPORT);

my_addr.sin_addr.s_addr=inet_addr("132.241.5.10");

bind(sockfd,(structsockaddr*)&my_addr,sizeof(struct

sockaddr));…….}

Socket基本编程技术30connect()函数功能建立套接字连接#include<sys/socket.h>函数原型intconnect(intsockfd,conststructsockaddr*serv_addr,socklen_taddrlen);参数说明sockfd:调用socket返回的文件描述符serv_addr:远程主机IP地址和端口addrlen:设置为sizeof(structsockaddr)返回值成功时,返回0失败时,返回-1Socket基本编程技术31connect()函数示例 #include<string.h>

#include<sys/types.h>

#include<sys/socket.h>

#defineDEST_IP"132.241.5.10"

#defineDEST_PORT23

intmain(){

intsockfd;

structsockaddr_indest_addr;

sockfd=socket(AF_INET,SOCK_STREAM,0);

dest_addr.sin_family=AF_INET;

dest_addr.sin_port=htons(DEST_PORT);

dest_addr.sin_addr.s_addr=inet_addr(DEST_IP);

connect(sockfd,(structsockaddr*)&dest_addr,

sizeof(structsockaddr));

Socket基本编程技术32listen()函数功能用于面向连接服务器,表明愿意接收连接#include<sys/socket.h>函数原型intlisten(intsockfd,intbacklog);参数说明sockfd:调用socket返回的文件描述符backlog:accept()应答之前,允许在进入队列中等待的连接数目,出错时返回-1返回值成功时,返回0失败时,返回-1说明在使用listen()之前,需要调用bind()绑定到需要的端口,否则系统内核将会监听一个随机端口socket();

bind();

listen();Socket基本编程技术33accept()函数功能建立套接字连接,处理单个连接请求(如发送/接收数据)#include<sys/socket.h>函数原型intaccept(intsockfd,structvoid*addr,socklen_t*addrlen);参数说明sockfd:正在监听端口的套接字文件描述符addr:指向本地数据结构sockaddr_in的指针调用connect()的信息将存储在该结构中addrlen:设置为sizeof(structsockaddr_in)返回值成功时,返回一个socket端口失败时,返回-1Socket基本编程技术34accept()函数intmain(){ intsockfd,client_fd; structsockaddr_in

remote_addr;

/*客户端地址信息*/ …… while(1){ sin_size=sizeof(structsockaddr_in); if((client_fd=accept(sockfd,(structsockaddr*)

&remote_addr,&sin_size))==-1){ perror("accept");continue; } printf("from%s\n",inet_ntoa(remote_addr.sin_addr)); …… } ……}

Socket基本编程技术35send()函数功能通过socket发送数据#include<sys/types.h>#include<sys/socket.h>函数原型ssize_tsend(intsockfd,constvoid*buf,size_tlen,intflags);参数说明sockfd:发送数据的套接字描述符msg:指向发送数据的指针len:数据长度flags:一般设置为0返回值成功时,返回实际发送的数据的字节数失败时,返回-1Socket基本编程技术36recv()函数功能通过socket接收数据#include<sys/types.h>#include<sys/socket.h>函数原型ssize_trecv(intsockfd,void*buf,size_tlen,intflags);参数说明sockfd:要读的SOCKET描述符buf:要读的信息的缓冲区len:缓冲的最大长度flags:一般设置为0返回值成功时,返回实际接收到的数据的字节数失败时,返回-1Socket基本编程技术37send()/recv()中的flags说明MSG_DONTROUTEsend()的使用标志,不查找路由表,表示目的主机在本地网络MSG_OOB接收或者发送带外数据MSG_PEEKrecv()的使用标志,查看数据但不从系统缓冲区移走数据MSG_WAITALLrecv()的使用标志,等待所有数据,阻塞式接收,直到满足条件或发生错误读到指定字节时,正常返回,返回值等于len读到文件尾,正常返回,返回值小于len操作错误时,返回-1Socket基本编程技术38带外数据传输层协议使用带外数据(out-of-band,OOB)来发送一些重要数据若通信一方有重要数据需要通知对方时,协议能将这些数据快速地发送到对方为发送这些数据,协议一般不使用与普通数据相同的通道,而是使用另外的通道Linux套接字机制支持低层协议发送/接收带外数据,但TCP协议没有真正意义上的带外数据为发送重要协议,TCP提供紧急模式机制TCP协议在数据段中设置URG位,表示进入紧急模式接收方可以对紧急模式采取特殊的处理这种方式数据不容易被阻塞,且可通过在服务器端程序里捕捉SIGURG信号来及时接收数据TCP协议每次只能发送和接收一个字节带外数据Socket基本编程技术39TCP发送带外数据的处理机制TCP总将最后一个字节当作OOB数据,其余当作普通字节不管通过带MSG_OOB标志的sendXXXX()函数发送多少字节OOB数据,发送端只将最后一个字节当作OOB数据接收端也只能收到一个字节的OOB数据举例:send(sendfd,"ABC",3,MSG_OOB)TCP将紧急模式URG置位紧急指针定位第三个字节(“C”)前两个字节("AB")当作普通字节发送

Socket基本编程技术40TCP接收带外数据的处理机制TCP提供两种处理模式非OOBINLINE模式:套接字的默认模式将OOB字节与普通字节分开存放,OOB字节存放在一个OOB缓冲区中OOBINLINE模式:OOB字节和普通字节一起存放recvXXXX函数在MSG_OOB模式下,将在OOB缓冲区中寻找数据如果发送端没发送OOB字节,它返回错误如果发送端发送了OOB字节对于非OOBINLINE模式,返回1字节的OOB数据对于OOBINLINE模式,返回错误,因为OOB字节没有放到OOB缓冲区中

Socket基本编程技术41sendto()函数功能用于数据报套接字的通信#include<sys/types.h>#include<sys/socket.h>函数原型intsendto(intsockfd,constvoid*msg,intlen,unsignedintflags,conststructsockaddr*to,inttolen);参数说明to:目地机的IP地址和端口号信息tolen:常被赋值为sizeof(structsockaddr)返回值成功时,返回实际发送的数据的字节数失败时,返回-1Socket基本编程技术42recvfrom()函数功能用于数据报套接字的通信#include<sys/types.h>#include<sys/socket.h>函数原型intrecvfrom(intsockfd,void*buf,intlen,unsignedintflags,structsockaddr*from,int*fromlen);参数说明from:保存源机的IP地址及端口号fromlen:常常被赋值为sizeof(structsockaddr)返回值成功时,返回实际接收到的数据的字节数失败时,返回-1Socket基本编程技术43write()函数函数原型ssize_t

write(int

fd,const

void

*buf,size_t

nbytes)功能将buf中的nbytes字节内容写入文件描述符fd返回值成功时返回写的字节数失败时返回-1,并设置errno变量说明返回值大于0,表示写入部分或全部数据返回值小于0,表示出现错误如果错误为EINTR,表示在写的时候出现中断错误如果为EPIPE,表示网络连接出现问题Socket基本编程技术44基于write()函数的socket写实现Socket基本编程技术45read()函数函数原型ssize_t

read(int

fd,void

*buf,size_t

nbyte)功能从fd中读取内容返回值读成功时,返回实际所读的字节数如果返回的值是0

表示已经读到文件的结束,出错时,返回值小于0如果错误为EINTR,说明读是由中断引起的如果是ECONNREST表示网络连接出了问题Socket基本编程技术46基于read()函数的socket读实现Socket基本编程技术47close()/shutdown()函数功能关闭通讯函数原型intclose(intsockfd);intshutdown(intsockfd,inthow);参数说明sockfd:要关闭的套接字描述符how:0:不允许接收1:不允许发送2:不允许发送和接收(和close()一样)返回值成功时,返回0失败时,返回-1Socket基本编程技术48getpeername()/gethostname()函数intgetpeername(intsockfd,structsockaddr*addr,int*addrlen);获取socket连接另一端的主机信息sockfd:是连接的数据流套接口文件描述符addr:保存另一端主机信息addrlen:设置为sizeof(structsockaddr)intgethostname(char*hostname,size_tsize);返回程序正在运行的计算机的名字返回值如果成功,返回0如果失败,返回-1

Socket基本编程技术49IP地址与域名的获取函数原型#include<netdb.h>structhostent*gethostbyname(constchar*name);structhostent*gethostbyaddr(constchar*addr,size_tlen,inttype);structhostent{char*h_name;/*主机的正式名称*/char**h_aliases;/*主机的别名*/inth_addrtype;/*主机的地址类型

AF_INET*/inth_length;/*主机的地址长度

对于IP4

是4字节32位*/char**h_addr_list;/*主机的IP地址列表*/#defineh_addrh_addr_list[0]/*主机的第一个IP地址*/};Socket基本编程技术50字符串的IP与32的IP的转换说明

网络上的IP都是数字加点(192.168.0.1)构成structin_addr结构使用32位的IP,如IP(C0A80001)是192.168.0.1函数原型intinet_aton(constchar*cp,structin_addr*inp)将a.b.c.d的IP转换为32位的IP,存储在inp指针里面char*inet_ntoa(structin_addrin)将32位IP转换为a.b.c.d的格式说明a代表ascii,n代表networkSocket基本编程技术51面向连接的socket通信流程客户端s=socket(),建立流式套接字,返回套接字号sconnect(s),将套接字s与远程主机连接recv(s)/send(s),在套接字s上读/写数据至完成交换close(s),关闭套接字s,结束TCP对话s=socket(),建立流式套接字,返回套接字号sbind(s),套接字s与本地地址相连listen(s),通知TCP服务器准备好接收连接ns=accept(s),接收连接,等待客户端的连接…建立连接,accept()返回,得到新的套接字nsclose(ns),关闭套接字nsrecv(ns)/send(ns),在套接字ns上读/写数据至完成交换服务器端close(s),关闭最初套接字s,服务结束Socket基本编程技术52面向连接socket通信流程服务器程序作用初始化服务器程序持续监听一个固定的端口收到客户的连接后建立一个socket连接与客户进行通信和信息处理接收客户通过socket连接发送来的数据,创建一个新的socket,通过socket连接与客户通信,进行相应处理,并返回处理结果通信结束后中断与客户的连接(关闭socket)Socket基本编程技术53面向连接的socket通信流程客户程序作用初始化客户程序连接到某个服务器上,建立socket连接与服务器进行通信和信息处理接收服务器通过socket连接发送来的数据,进行相应处理通过socket连接向服务器发送请求信息通信结束后中断与客户的连接Socket基本编程技术54面向连接socket通信示例—服务器程序Socket基本编程技术55面向连接socket通信示例—服务器程序Socket基本编程技术56面向连接socket通信示例—服务器程序Socket基本编程技术57面向连接socket通信示例—服务器程序Socket基本编程技术58面向连接socket通信示例—客户程序Socket基本编程技术59面向连接socket通信示例—客户程序Socket基本编程技术60面向连接socket通信示例—客户程序Socket基本编程技术61面向无连接socket通信流程客户端s=socket(),建立数据报套接字,返回套接字号sbind(s),将套接字s与本地主机连接(可选)recvfrom(s)/sendto(s),在套接字s上读/写数据至完成交换close(s),关闭套接字s,结束UDP对话bind(s),套接字s与本地地址相连s=socket(),建立数据报套接字,返回套接字号srecvfrom(s)/sendto(s),在套接字s上读/写数据至完成交换close(s),关闭套接字s服务器端Socket基本编程技术62面向无连接通信适用场景面向数据报网络数据大多为短消息拥有大量客户对数据安全性无特殊要求网络负担非常重,但对响应速度要求高Socket基本编程技术63面向无连接socket通信示例—公共函数Socket基本编程技术64面向无连接socket通信示例—公共函数Socket基本编程技术65面向无连接socket通信示例—服务程序Socket基本编程技术66面向无连接socket通信示例—服务程序Socket基本编程技术67面向无连接socket通信示例—服务器程序Socket基本编程技术68面向无连接socket通信示例—客户程序Socket基本编程技术69面向无连接socket通信示例—客户程序Socket基本编程技术70服务器请求处理流程—循环服务器方案UDP实现框架没有一个客户端可以一直占用服务端只要处理过程不是死循环,则服务器对于每一个客户机的请求总是能够满足

socket(...);

bind(...);

while(1)

{

recvfrom(...);

process(...);

sendto(...);

}

Socket基本编程技术71服务器请求处理流程—循环服务器方案TCP实现框架每次接受一个客户端连接完成某客户所有请求后,断开连接

socket(...);

bind(...);

listen(...);

while(1){

accept(...);

{

recv(...);

process(...);

send(...);

}

close(...);

}Socket基本编程技术72服务器请求处理流程—并发服务器方案TCP实现框架

s=socket(...);

bind(s,...);

listen(s,...);

while(1)

{

ns=accept(s,...);

if(fork(..)==0)

{

recv(ns,...);

process(...);

send(ns,...);

close(ns);}

}

}

Socket基本编程技术73多线程客户/服务器示例—线程实现功能描述客户端使用线程向服务器发送从标准输入得到的字符在主线程中将从服务器端返回的字符显示到标准输出服务器端将客户端发来的数据原样返回给客户端,每一个客户在服务器上对应一个线程Socket基本编程技术74多线程客户/服务器示例—线程实现公共文件Socket基本编程技术75多线程客户/服务器示例—线程实现客户端Socket基本编程技术76多线程客户/服务器示例—线程实现客户端Socket基本编程技术Sockfd未实例化!!!77多线程客户/服务器示例—线程实现服务器端Socket基本编程技术pthread_detach(thread_id)(非阻塞,可立即返回)这将该子线程的状态设置为detached,则该线程运行结束后会自动释放所有资源。78多线程客户/服务器示例—线程实现服务器端Socket基本编程技术79目录网络通信协议基础Socket基本编程技术Socket高级编程技术80阻塞式I/O可能造成阻塞的函数有:connect()、accept()、读写函数、select()、poll()、gethostbyname()等Socket高级编程技术81非阻塞式I/O调用可能造成阻塞的函数时,若发生阻塞,函数返回-1并将errno设置为EAGAIN或EWOULDBLOCK,程序可继续向下运行非阻塞模式需要程序不断检查各个可能阻塞的函数的状态当一个应用程序使用了非阻塞模式的套接字,它需要使用一个循环来不停的测试是否一个文件描述符有数据可读(称做p

温馨提示

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

评论

0/150

提交评论