网络编程_第2讲Socket网络编程基础.ppt

上传人:qwe****56 文档编号:70011936 上传时间:2023-01-14 格式:PPT 页数:47 大小:1.61MB
返回 下载 相关 举报
网络编程_第2讲Socket网络编程基础.ppt_第1页
第1页 / 共47页
网络编程_第2讲Socket网络编程基础.ppt_第2页
第2页 / 共47页
点击查看更多>>
资源描述

《网络编程_第2讲Socket网络编程基础.ppt》由会员分享,可在线阅读,更多相关《网络编程_第2讲Socket网络编程基础.ppt(47页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、南昌大学软件学院南昌大学软件学院第第2讲讲 Socket网络编程基础网络编程基础l套接字网络编程接口的产生与发展过程l套接字编程的基本概念l套接字的特点、应用场合、使用的数据类型l面向连接的套接字编程l套接字的工作过程、系统调用、编程实例l借助实例分析进程的阻塞问题和对策l无连接的套接字编程l无连接套接字编程的两种模式(C/S和对等)l数据报套接字的对等模式编程实例南昌大学软件学院南昌大学软件学院2.1套接字网络编程接口的产生与发展套接字网络编程接口的产生与发展2.1.1问题的提出问题的提出l应用程序与协议软件进行交互时须说明许多细节应用程序与协议软件进行交互时须说明许多细节:l是服务器还是客

2、户机,主动还是被动通信?l发送方需说明发送的数据;l接收方需说明接收的数据如何存放。l站在应用程序实现的角度,应用程序如何方便地使用协议栈软件进行通信呢?l如果能在应用程序与协议栈软件之间提供一个软件接口,就可以方便客户与服务器软件的编程。lUNIX最早将最早将TCP/IP协议簇集成到内核中,协议簇集成到内核中,UNIX的开发者提出并实现了套接字应用编程接口。的开发者提出并实现了套接字应用编程接口。南昌大学软件学院南昌大学软件学院l套接字应用程序编程接口:套接字应用程序编程接口:是网络应用程序通过网是网络应用程序通过网络协议栈进行通信时所使用的接口,即应用程序与络协议栈进行通信时所使用的接口,

3、即应用程序与协议栈软件之间的接口,简称协议栈软件之间的接口,简称套接字编程接口套接字编程接口(SocketAPI)。l定义了应用程序与协议栈软件进行交互时可以使用的一组操作,决定了应用程序使用协议栈的方式、应用程序所能实现的功能、以及开发具有这些功能的程序的难度。l套接字编程接口给出了应用程序能够调用的一组过程,以及这些过程所需的参数,每个独立的过程完成一个与协议栈软件交互的基本操作(如:建立连接、接收数据、释放链接)。南昌大学软件学院南昌大学软件学院2.1.2套接字编程接口的起源与应用套接字编程接口的起源与应用l加州大学伯克利分校开发了一个包括TCP/IP协议簇的BSD UNIX,并迅速得到

4、推广,套接字编程接口是这个操作系统一部分。lTCP/IP标准并没有定义应用程序用来与该协议进标准并没有定义应用程序用来与该协议进行交互的应用程序编程接口,只规定了应该提供行交互的应用程序编程接口,只规定了应该提供的一般操作,并允许各个操作系统去定义用来实的一般操作,并允许各个操作系统去定义用来实现这些操作的具体现这些操作的具体API。l一个协议标准可能只是建议某个操作在应用程序发送数据时是需要的,而由应用程序编程接口来定义具体的函数名和每个参数的类型。南昌大学软件学院南昌大学软件学院l尽管协议标准允许操作系统设计者开发自己的应尽管协议标准允许操作系统设计者开发自己的应用程序编程接口,但由于用程

5、序编程接口,但由于BSDUNIX的广泛使用,的广泛使用,后来的许多操作系统及编程语言都选择了对套接后来的许多操作系统及编程语言都选择了对套接字编程接口的支持。字编程接口的支持。l由于这个套接字规范最早是由由于这个套接字规范最早是由Berkeley大学开发的,大学开发的,一般将它称为一般将它称为BerkeleySockets规范。规范。lBerkeley Sockets规范规定了一系列与套接字使用有关的库函数,为在UNIX操作系统下不同计算机中的应用程序进程之间,使用TCP/IP协议簇进行网络通信提供了一套应用程序编程接口。南昌大学软件学院南昌大学软件学院2.1.3套接字编程接口的两种实现方式套

6、接字编程接口的两种实现方式l采用两种实现套接字编程接口的方式:采用两种实现套接字编程接口的方式:l在操作系统的内核中增加相应的软件来实现;l通过开发操作系统之外的函数库来实现。l在在BSDUNIX及起源于它的操作系统中,套接字函数是及起源于它的操作系统中,套接字函数是操作系统本身的功能调用,是操作系统内核的一部分。操作系统本身的功能调用,是操作系统内核的一部分。l其他操作系统供应商为了不修改基本操作系统,开发了其他操作系统供应商为了不修改基本操作系统,开发了套接字库(套接字库(SocketLibrary)来提供套接字编程接口。)来提供套接字编程接口。l套接字库中的每个过程具有与UNIX套接字函

7、数相同的名字与参数,向没有本机套接字的操作系统上的应用程序提供套接字编程接口。l套接字库与操作系统内核中实现的套接字套接字库与操作系统内核中实现的套接字在语义在语义上是相同的上是相同的。l应用程序调用套接字过程不必管它是由操作系统内核过程提供的,还是由库过程提供的。l这种方式提供了程序的可移植性:将程序从一台计算机移植到另一台计算机时,程序的源代码不需改动,只要用新计算机上的套接字库重新编译即可。l套接字库与操作系统直接提供的本机套接字编程套接字库与操作系统直接提供的本机套接字编程接口接口在实现上是不同的在实现上是不同的。l套接字库的过程需要链接到应用程序中;l并驻留于应用程序地址空间;l调用

8、时控制从应用程序转向库程序,并进一步调用一个或多个底层操作系统的功能调用。南昌大学软件学院南昌大学软件学院2.2套接字编程的基本概念套接字编程的基本概念图图2.1电插座与电话插座的作用电插座与电话插座的作用2.2.1什么是套接字(什么是套接字(SOCKET)l套接字是对网络中不同主机上应用进程之间进行双向套接字是对网络中不同主机上应用进程之间进行双向通信的端点的抽象。通信的端点的抽象。l一个套接字就是网络上进程通信的一端,提供了应用一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议栈交换数据的机制层进程利用网络协议栈交换数据的机制。南昌大学软件学院南昌大学软件学院图图2.2应用进

9、程、套接口、网络协议栈及操作系统的关系应用进程、套接口、网络协议栈及操作系统的关系l两个应用进程只要分别连接到自己的套接字,就可以通过网络痛惜,不用去管复杂的网络结构及数据传输过程。l从多个层面来理解套接字这个概念的内涵从多个层面来理解套接字这个概念的内涵l从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议栈进行通信的接口,是应用程序与网络协议栈交互的接口.l从实现的角度来讲,非常复杂。套接字是一个复杂的软件机构,包含了一定的数据结构,包含许多选项,由操作系统内核管理。l从使用的角度来讲,非常简单。对套接字的操作形成了一种网络应用程序的编程接口(API),提供了一组系

10、统调用或库函数,可以用于构造套接字、安装绑定套接字、连接套接字、通过套接字交换数据、关闭套接字,实现各种分布式应用。l l套接字编程接口套接字编程接口套接字编程接口套接字编程接口是一套操作套接字的编程接口函数,是一套操作套接字的编程接口函数,套接字是它的操作对象。套接字是它的操作对象。南昌大学软件学院南昌大学软件学院2.2.2套接字的特点套接字的特点1 1通信域通信域l通信域:通信域:是一个计算机网络的范围,在这个范围中,所有的计算机使用同一种网络体系结构及协议栈。l套接字存在于通信域中。套接字存在于通信域中。l套接字通常只和同一域中的套接字交换数据。l如果数据交换要穿越域的边界,就一定要执行

11、某种解释程序。l这里,仅仅针对这里,仅仅针对Internet域,并且使用域,并且使用Internet协协议族(即议族(即TCP/IP协议族)来通信。协议族)来通信。南昌大学软件学院南昌大学软件学院2 2套接字具有三种类型套接字具有三种类型l每一个正被使用的套接字都有它确定的类型。l只有相同类型的套接字才能相互通信。(1)数据报套接字(数据报套接字(DatagramSOCKET)l数据报套接字提供无连接的、不保证可靠的、独数据报套接字提供无连接的、不保证可靠的、独立的数据报传输服务。立的数据报传输服务。l在在Internet通信域中,数据报套接字使用通信域中,数据报套接字使用UDP数据数据报协议

12、形成的进程间通路,具有报协议形成的进程间通路,具有UDP协议为上层协议为上层所提供的服务的所有特点。所提供的服务的所有特点。l一般用于轻载通信,并具有多播通信的能力。一般用于轻载通信,并具有多播通信的能力。南昌大学软件学院南昌大学软件学院图图2.3在在Internet通信域中,数据报套接字基于通信域中,数据报套接字基于UDP协议协议南昌大学软件学院南昌大学软件学院(2)流式套接字(流式套接字(StreamSOCKET)l流式套接字提供双向的、有序的、无重复的、无流式套接字提供双向的、有序的、无重复的、无记录边界的可靠的数据流传输服务。记录边界的可靠的数据流传输服务。l在在Internet通信域

13、中,流式套接字使用通信域中,流式套接字使用TCP协议形协议形成的进程间通路,具有成的进程间通路,具有TCP协议为上层所提供的协议为上层所提供的服务的所有特点。服务的所有特点。l在使用流式套接字传输数据之前,必须在数据的在使用流式套接字传输数据之前,必须在数据的发送端和接收端之间建立连接。发送端和接收端之间建立连接。l一般用于交换大批量的数据时,或者要求数据按一般用于交换大批量的数据时,或者要求数据按照发送的顺序无重复的到达目的地的时候。照发送的顺序无重复的到达目的地的时候。南昌大学软件学院南昌大学软件学院图图2.4在在Internet通信域中,流式套接字基于通信域中,流式套接字基于TCP协议协

14、议南昌大学软件学院南昌大学软件学院(3)原始式套接字(原始式套接字(RAWSOCKET)l原始式套接字允许对较低层次的协议原始式套接字允许对较低层次的协议(如如IP、ICMP)直接访问,用于检验新协议的实现。直接访问,用于检验新协议的实现。l原始套接字保存了数据包中的完整IP头;l前面两种套接字只能收到用户数据;l因此可以通过原始套接字对数据进行分析。南昌大学软件学院南昌大学软件学院2.2.3套接字的应用场合套接字的应用场合l并非所有的网络应用编程都要使用套接字。并非所有的网络应用编程都要使用套接字。l套接字适合开发具有如下特点的新网络应用。套接字适合开发具有如下特点的新网络应用。l不管是采用

15、对等模式或者客户机/服务器模式,通信双方的应用程序都需要开发。l双方所交换数据的结构和交换数据的顺序有特定的要求,不符合现在成熟的应用层协议,甚至需要自己去开发应用层协议,自己设计最适合的数据结构和信息交换规程。l套接字编程层次较低,自由度较大。套接字编程层次较低,自由度较大。南昌大学软件学院南昌大学软件学院2.3面向连接的套接字编程面向连接的套接字编程2.3.1套接字的工作过程套接字的工作过程l面向连接的通信方式基于面向连接的通信方式基于TCP,必须借助流式套,必须借助流式套接字来编程,应用服务器分为服务器端和客户端,接字来编程,应用服务器分为服务器端和客户端,双方是不对称的,需要分别编程。

16、双方是不对称的,需要分别编程。l双方首先要创建并安装套接字,做好准备;l建立连接,采用三次握手的方式;l数据交换,称为客户机与服务器的会话期,会话的内容必须遵守一定的格式和顺序;l释放连接。l下面介绍面向连接的服务器和客户端的编程步骤下面介绍面向连接的服务器和客户端的编程步骤.南昌大学软件学院南昌大学软件学院2.3.2套接字编程接口的系统调用套接字编程接口的系统调用1创建套接字创建套接字SOCKET()l创建一个套接字,并返回一个整型描述符:创建一个套接字,并返回一个整型描述符:intSOCKET(intProtofamily,intType,intProtocol);l入口参数:入口参数:l

17、Protofamily:套接字使用的协议簇,一般为PF_INET,表示TCP/IP协议簇,PF_DECnet表示DEC协议。ltype:套接字类型,SOCK_STREMA表示创建面向连接的流传输的流式套接字;SOCK_DGRAMA表示创建无连接的面向消息的数据报套接字。lprotocol:套接字使用的传输层网络协议,一般为IPPROTO_IP,internet通信域中一般取值为0。南昌大学软件学院南昌大学软件学院l返回值:返回值:l套接字创建成功,返回一个int型的整数,即所创建套接字的描述符,指向被维护在操作系统内核里的socket数据结构。l套接字创建出错,返回1,表示出错类型的代码保存在

18、全局变量Errno中。l举例:举例:intsockfd=SOCKET(PF_INTE,SOCK_STREAM,0)l创建套接字时,为其分配了内存,并建立了相应的数据结构,用于指定连接的种类和使用的协议,同时还有关于连接队列操作的选项结构字段,创建时设置为默认值。南昌大学软件学院南昌大学软件学院2绑定套接字到指定的地址绑定套接字到指定的地址BIND()lintBIND(intSockfd,structsockaddr*My_addr,intAddrlen);l入口参数:入口参数:lSockfd:是由SOCKET()系统调用创建的套接字描述符,要将其绑定到指定的网络地址上;lMy_addr:指向s

19、ockaddr结构变量的指针,所指结构中保存着特定的网络地址,要将套接字绑定到这个网络地址上;lAddlen:是sockaddr结构的长度。南昌大学软件学院南昌大学软件学院l返回值:返回值:l如果返回0,表示已经绑定成功。l如果返回1,表示有错,出错码在Errno中。l举例:举例:Structsockaddr_inmy_addr;if(BIND(sockfd,(sockaddr*)&my_addr,sizeof(structsockaddr_in)0)报错,并退出l在服务器端,用作监听客户机连接请求的套接字一定要绑定,因为大多数服务器进程使用熟知端口,并且服务器有时有多块网卡,会有多个IP地址

20、。l客户机一般不用绑定。南昌大学软件学院南昌大学软件学院3启动监听启动监听Listen()lintLISTEN(intSockfd,intQueuesize);l入口参数:入口参数:lSockfd:套接字描述符,通过它来监听来自客户机端的连接请求。lQueuesize:等待连接队列的最大长度,最大可设为20,一般设为510。l返回值:返回值:l函数正确执行则返回0,出错则返回-1。l举例:举例:LISTEN(Sockfe,10);南昌大学软件学院南昌大学软件学院举例:举例:LISTEN(Sockfe,10);图图2.6监听套接字使用缓冲区接纳多个客户端的连接请求监听套接字使用缓冲区接纳多个客户

21、端的连接请求南昌大学软件学院南昌大学软件学院4接收连接请求接收连接请求ACCEPT()lintACCEPT(intSockfd,structsockaddr*Addr,int*addrlen);l入口参数:入口参数:lSockfd:监听客户端连接请求的套接字描述符。lAddr:sockaddr结构变量的指针,是一个出口参数,当调用执行完毕时,变量中放置的是所接收客户机端的网络地址。lAddrlen:整型变量指针,也是一个出口参数,调用时初始设置为Addr结构的长度,不能为0或null,调用执行完毕时,返回所接收的客户机端网络地址长度。南昌大学软件学院南昌大学软件学院l返回值:返回值:l如果执行

22、正确,返回一个新的套接字描述符,这个套接字已经与客户机端建立了连接,并专用于此后与客户机端交换数据。l如果出错,返回1。l说明:说明:l调用从监听套接字的等待队列中,取出第一个连接请求,创建一个新的套接字,并通过这个新套接字向客户机端发送连接应答,从而与客户机端建立连接,系统为这个新的套接字分配一个服务器端的自由端口号,这个套接字用于后续与客户机端交换数据,称为响应套接字。南昌大学软件学院南昌大学软件学院举例:int clientfd;/定义响应套接字描述符变量int addrler=sizeof(sockaddr);/获得套接字地址结构长度。struct sockaddr_in cltsoc

23、kaddr;/定义用于返回客户端地址的结构。clientfd=ACCEPT(listenfd,(sockaddr*)(&cltsockaddr),&addrlen);/接收客户连接请求 南昌大学软件学院南昌大学软件学院5请求建立连接请求建立连接CONNECT()lintCONNECT(intSockfd,structsockaddr*Service_addr,intAddrlen);l入口参数:入口参数:lSockfd:客户机端的请求套接字;lService_addr:存放服务器端的网络地址;lAddrlen:sockaddr结构的长度。l返回值:返回值:l连接成功,返回0;l连接未成功,返回

24、-1。南昌大学软件学院南昌大学软件学院l说明:说明:l用于客户端请求连接到服务器;l对于流式套接字,使用TCP协议,服务器若接受连接请求,即把它放入监听套接字的缓冲区队列,并调用ACCEPT()来接收处理;l对于数据报套接字,使用UDP协议,客户机向同一服务器传送多条信息时,允许客户机使用CONNECT只指明服务器地址一次,而不必在每条信息中都指明目的地址。l举例:举例:if(CONNECT(sockfd,(structsockaddr*)(&serv_addr),sizeof(structsockaddr)0)南昌大学软件学院南昌大学软件学院6读读/写套接字写套接字READ()和和WRITE

25、()lintREAD(intsockfd,void*buffer,intlen)lintWRITE(intsockfd,void*buffer,intlen)l入口参数:入口参数:lSockfd:要读/写的套接字描述符,在客户机端是请求套接字,在服务器端是响应套接字;lBuffer:指向内存中用来存放数据的读写缓冲区,读套接字时存放从套接字接收到的数据,写套接字的时候存放要发送的数据;lLen:读写缓冲区的长度。南昌大学软件学院南昌大学软件学院l返回值:返回值:l对于read()返回实际读到的字符数。南昌大学软件学院南昌大学软件学院7发送发送SEND()和接收和接收RECV()intSEND(

26、intsockfd,char*buf,intlen,intflags);intRECV(intsockfd,char*buf,intlen,intflags);l入口参数:入口参数:lsockfd:用来发送/接收数据的套接字描述符,可以是由SOCKET()创建的,也可以是ACCEPT()返回的;lbuf:用于发送/接收数据的缓冲区指针;llen:发送或接收的字符数;lflags:执行本调用的方式,一般置为0.南昌大学软件学院南昌大学软件学院l返回值:返回值:l处理错误,返回-1;l如果正确,对于发送返回实际发送出去的字节数;对于接收返回实际读入缓冲区的字节数。l说说明:明:l和read、wri

27、te一样,必须用于已连接的套接字,无需调用者指明目的地参数。南昌大学软件学院南昌大学软件学院l8关闭套接字关闭套接字CLOSE()intCLOSE(intsockfd);l入口参数:入口参数:lsockfd:要关闭的套接字描述符。l说明:说明:l如果是面向连接的,CLOSE在关闭套接字前先终止连接;l关闭一个套接字意味着立即终止对它的使用,描述符被释放,以防止应用程序发送或接收更多的数据。南昌大学软件学院南昌大学软件学院关于阻塞的问题关于阻塞的问题 图图2.7服务器进程因调用服务器进程因调用ACCEPT()而被阻塞而被阻塞南昌大学软件学院南昌大学软件学院2.3.4进程的阻塞问题和对策进程的阻塞

28、问题和对策1什么是阻塞什么是阻塞l阻塞:阻塞:是指一个进程执行了一个函数或者系统调是指一个进程执行了一个函数或者系统调用,该函数由于某种原因不能立即完成,因而不用,该函数由于某种原因不能立即完成,因而不能返回调用它的进程,导致进程受控于这个函数能返回调用它的进程,导致进程受控于这个函数而处于等待的状态,进程的这种状态称为阻塞。而处于等待的状态,进程的这种状态称为阻塞。南昌大学软件学院南昌大学软件学院图图2.8RECV()函数的两种执行方式函数的两种执行方式南昌大学软件学院南昌大学软件学院2 2能引起阻塞的套接字调用能引起阻塞的套接字调用l在在Berkeley套接字网络编程接口的模型中,套接字套

29、接字网络编程接口的模型中,套接字的默认行为是阻塞的,具体地说,在一定情况下,的默认行为是阻塞的,具体地说,在一定情况下,有多个操作套接字的系统调用会引起进程阻塞。有多个操作套接字的系统调用会引起进程阻塞。(1)ACCEPT()(2)READ()、RECV()和READFORM()(3)WRITE()、SEND()和SENDTO()(4)CONNECT()(5)SELECT()(6)CLOSESOCKET()南昌大学软件学院南昌大学软件学院图图2.9采用阻塞工作模式的服务器不能很好地为多个客户服务采用阻塞工作模式的服务器不能很好地为多个客户服务3 3阻塞工作模式带来的问题阻塞工作模式带来的问题l

30、采用阻塞工作模式的单进程服务器,不能很好地采用阻塞工作模式的单进程服务器,不能很好地同时为多个客户服务的。图同时为多个客户服务的。图2.9是一个例子。是一个例子。南昌大学软件学院南昌大学软件学院2.4无连接的套接字编程无连接的套接字编程2.4.1无连接的套接字编程的两种模式无连接的套接字编程的两种模式l使用数据报套接字开发网络应用程序,既可以采使用数据报套接字开发网络应用程序,既可以采用客户用客户/服务器模式,也可以采用对等模式。服务器模式,也可以采用对等模式。南昌大学软件学院南昌大学软件学院图图2.10对等模式的数据报套接字的编程模型对等模式的数据报套接字的编程模型1对等模式对等模式 南昌大

31、学软件学院南昌大学软件学院l对等模式无连接套接字特点:对等模式无连接套接字特点:l应用双方是对等的:要经过4个阶段,创建套接字、绑定套接字、发送/接收数据、关闭套接字;l双方都必须确切知道对方的网络地址,并在各自的进程中将约定好的网络地址绑定到自己的套接字上;l每一次传递数据时,在sendto和recvfrom系统调用中必须包含对方的网络地址信息;l进程也会因为发送或接收数据而发生阻塞。南昌大学软件学院南昌大学软件学院2客户客户/服务器模式服务器模式 图图2.11C/S模式的数据报套接字的编程模型模式的数据报套接字的编程模型南昌大学软件学院南昌大学软件学院lC/S模式无连接套接字特点:模式无连

32、接套接字特点:l应用双方不是对等的:服务器要先启动,被动等待访问,要经过创建套接字、绑定套接字、发送/接收数据、关闭套接字4个阶段,将套接字绑定到众所周知的端口上;l客户机套接字使用动态分配的自由端口上,不需要进行绑定;l客户机主动请求服务,并在数据报中携带双方的地址;l服务器可以接受多个客户端的数据。2.4.2两个专用的系统调用两个专用的系统调用1 1发送数据报发送数据报SENDTO()lint SENDTO(int sockfd,const void*msg,int len,unsigned int flags,struct sockaddr*to,int tolen);l入口参数:入口参

33、数:lSockfd:发送方的描述符,包含发送方的网络地址;lmsg:字符串指针,指向发送缓冲区;llen:发送缓冲区长度;lFlags:发送方式,一般为0;lTo:指向sockaddr结构的指针,包含接收方的网络地址;lTolen:sockaddr的结构长度。l返回值:成功返回发送字节数,失败返回返回值:成功返回发送字节数,失败返回1.2 2接收数据报接收数据报 RECVFROM()lint RECVFROM(int sockfd,void*buf,int len,unsigned int flags,struct sockaddr*from,int*fromlen)l入口参数:入口参数:lSockfd:接收方的描述符,包含发送方的网络地址;lmsg:字符串指针,指向接收缓冲区;llen:接收缓冲区长度;lflags:接收方式,一般为0;lFrom:指向sockaddr结构的指针,是个出口参数,调用接收后包含发送方的网络地址;lFromlen:出口参数,sockaddr的结构长度。l返回值:成功返回接收的字节数,失败返回返回值:成功返回接收的字节数,失败返回1.

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 技术资料 > 其他杂项

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁