1、Transport Layer,3-1,Chapter 3 Transport Layer,Computer Networking: A Top Down Approach 6th edition Jim Kurose, Keith Ross Addison-Wesley March 2012,A note on the use of these ppt slides: Were making these slides freely available to all (faculty, students, readers). Theyre in PowerPoint form so you s
2、ee the animations; and can add, modify, and delete slides (including this one) and slide content to suit your needs. They obviously represent a lot of work on our part. In return for use, we only ask the following:,If you use these slides (e.g., in a class) that you mention their source (after all,
3、wed like people to use our book!) If you post any slides on a www site, that you note that they are adapted from (or perhaps identical to) our slides, and note our copyright of this material.Thanks and enjoy! JFK/KWRAll material copyright 1996-2012J.F Kurose and K.W. Ross, All Rights Reserved,Transp
4、ort Layer,3-2,Chapter 3: 传输层,Our goals: 理解传输层服务原理: 多路复用与多路分解 可靠数据传输 流量控制 拥塞控制,学习因特网的传输层协议: UDP: 无连接传输 TCP: 面向连接的传输 TCP拥塞控制,Transport Layer,3-3,Chapter 3 outline,3.1 Transport-layer services 3.2 Multiplexing and demultiplexing 3.3 Connectionless transport: UDP 3.4 Principles of reliable data transfer
5、,3.5 Connection-oriented transport: TCP segment structure reliable data transfer flow control connection management 3.6 Principles of congestion control 3.7 TCP congestion control,Transport Layer,3-4,3.1 传输服务,在应用程序看来, 源进程向本地套接字写入报文,目的进程在本地套接字即可收到报文 源进程和目的进程仿佛直接连接在一起 传输层提供了进程间的逻辑通信 在传输层看来, 发送方传输层将报文交
6、给本地网络层接口,接收方传输层从本地网络层接口即可收到报文 网络层提供了终端间的逻辑通信,Transport Layer,3-5,传输层和网络层的关系,网络层: 提供主机之间的逻辑通信 传输层: 提供进程之间的逻辑通信 传输层依赖并增强网络层服务,Household analogy: 一个家庭的12个孩子和另一个家庭的12个孩子通信,分别推选Ann和Bill负责收集和邮寄信件,以及查看信箱和分发信件 进程 = 孩子 应用报文 = 信 传输层 = Ann 和 Bill(提供人到人的服务) 主机 = 住宅 网络层 = 邮政系统(提供门到门的服务),Transport Layer,3-6,传输服务和
7、网络服务,网络层提供尽力而为的服务: 网络层尽最大努力在主机间交付分组,但不提供任何承诺 具体来说,不保证交付,不保证按序交付,不保证数据完整,不保证延迟,不保证带宽,传输层不能提供的服务: 延迟保证 带宽保证传输层可以提供的服务: 保证可靠、按序的交付:TCP 不保证可靠、按序的交付:UDP,Transport Layer,3-7,Chapter 3 outline,3.1 Transport-layer services 3.2 Multiplexing and demultiplexing 3.3 Connectionless transport: UDP 3.4 Principles
8、of reliable data transfer,3.5 Connection-oriented transport: TCP segment structure reliable data transfer flow control connection management 3.6 Principles of congestion control 3.7 TCP congestion control,Transport Layer,3-8,3.2 多路复用与多路分解,process,socket,transport,application,physical,link,network,P2
9、,P1,transport,application,physical,link,network,P4,transport,application,physical,link,network,P3,传输层基本服务:将主机间交付扩展到进程间交付,如何进行多路复用和多路分解?,为将邮件交付给收信人: 每个收信人应有一个信箱,写有收信人地址和姓名(唯一标识) 信封上有收信人地址和名字,为将报文段交付给套接字: 主机中每个套接字应分配一个唯一的标识 报文段中包含接收套接字的标识,Transport Layer,3-9,多路复用: 发送方传输层将源/目的套接字标识置于报文段中,交给网络层 多路分解: 接收
10、方传输层根据报文段中的目的套接字标识,将报文段交付到正确的套接字,Transport Layer,3-10,套接字与端口号,端口号是套接字标识的一部分 每个套接字在本地关联一个端口号 端口号: 一个16比特的数 01023由公共域协议使用,称众所周知的端口号 报文段中有两个字段携带端口号 源端口号:与发送进程关联的本地端口号 目的端口号:与接收进程关联的本地端口号,source port #,dest port #,32 bits,application data (message),other header fields,TCP/UDP报文段格式,如何分配UDP套接字的端口号?,自动分配:
11、例如,new Datagramsocket(),不指定端口号 通常由操作系统从102465535中分配 客户端通常使用这种方法 使用指定端口号创建套接字: 例如,new Datagramsocket(53) 实现公共域协议的服务器应分配众所周知的端口号 服务器通常采用这种方法UDP套接字标识为二元组,Transport Layer,3-11,UDP多路分解,接收方传输层收到一个UDP报文后: 检查报文中的目的端口号,将UDP报文交付到具有该端口号的套接字相同的UDP报文被交付给同一个套接字,与 无关 报文中的 被接收进程用来发送响应报文,Transport Layer,3-12,Transpo
12、rt Layer,3-13,UDP多路分解: 举例,DatagramSocket serverSocket = new DatagramSocket(6428);,transport,application,physical,link,network,P3,transport,application,physical,link,network,P1,transport,application,physical,link,network,P4,DatagramSocket mySocket1 = new DatagramSocket (5775);,DatagramSocket mySocket
13、2 = new DatagramSocket(9157);,创建TCP套接字,服务器在port=x创建一个欢迎套接字: welcomeSocket = new ServerSocket(x) 客户A创建一个与欢迎套接字通信的客户套接字(假设自动分配端口号y): clientSocket = new Socket(“hostname”, x) 服务器在收到客户A的连接请求后创建一个连接套接字: connectionSocket = welcomeSocket.accept() 该连接套接字只与客户A的套接字通信,即只接收具有以下四元组的报文段: 源IP地址 = 客户A的IP地址 源端口号 = y
14、 目的IP地址 = 服务器的IP地址 目的端口号= x 不同的客户进程与服务器上不同的连接套接字对应,Transport Layer,3-14,Transport Layer,3-15,TCP多路分解,服务器主机可能有多个连接套接字每个连接套接字与一个进程相联系,并由 四元组进行标识服务器使用该四元组将报文段交付到正确的连接套接字,Transport Layer,3-16,TCP多路分解: 举例,transport,application,physical,link,network,P3,transport,application,physical,link,transport,applica
15、tion,physical,link,network,P2,host: IP address A,host: IP address C,server: IP address B,network,P3,P4,threaded server,小结,UDP套接字,使用二元组标识套接字 服务器使用一个套接字服务所有客户,TCP套接字,使用 四元组标识连接套接字 服务器使用多个连接套接字,每个连接套接字服务一个客户,Transport Layer,3-17,Transport Layer,3-18,Chapter 3 outline,3.1 Transport-layer services 3.2 Mu
16、ltiplexing and demultiplexing 3.3 Connectionless transport: UDP 3.4 Principles of reliable data transfer,3.5 Connection-oriented transport: TCP segment structure reliable data transfer flow control connection management 3.6 Principles of congestion control 3.7 TCP congestion control,Transport Layer,
17、3-19,UDP: User Datagram Protocol RFC 768,网络层提供的服务 尽最大努力将数据包交付到目的主机 不保证可靠性和顺序 不保证带宽及延迟UDP提供的服务: 多路复用和多路分解:将数据交付到进程 检错(可选):检测并丢弃出错的报文,但不尝试恢复UDP不提供: 可靠交付 按顺序交付 延迟及带宽保证,Transport Layer,3-20,3.3.1 UDP报文结构,UDP报文: 报头:协议处理需要的信息 载荷(payload):报文携带的数据 用于多路复用/多路分解的字段: 源端口号,目的端口号 用于检测报文错误的字段: 报文长度,检查和,source port
18、 #,dest port #,32 bits,Application data (message),UDP报文格式,length,checksum,报文长度(字节数),Transport Layer,3-21,3.3.2 UDP检查和(checksum),发送方: 将报文看成是由16比特整数组成的序列 对这些整数序列计算检查和 将检查和放到UDP报文的checksum字段,接收方: 对收到的报文进行相同的计算 与报文中的checksum字段进行比较: 不相等:报文段有错误 相等:认为没有错误,目的: 对传输的报文进行检错,Transport Layer,3-22,Internet checks
19、um: example,example: add two 16-bit integers,1 1 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 11 1 0 1 1 1 0 1 1 1 0 1 1 1 0 1 11 1 0 1 1 1 0 1 1 1 0 1 1 1 1 0 0 1 0 1 0 0 0 1 0 0 0 1 0 0 0 0 1 1,wraparound,sum,checksum,Note: when adding numbers, a carryout from the most significant
20、 bit needs to be added to the result,UDP检查和计算,计算UDP检查和包括伪头、UDP头和数据三个部分。 检查和的使用是可选的,若不计算检查和,该字段填入0。,检查和计算举例,计算检查和时,checksum字段填0 接收方对UDP报文(包括检查和)及伪头求和,若结果为0xFFFF,认为没有错误。,Transport Layer,3-24,Transport Layer,为什么需要UDP?,应用可以尽可能快地发送报文: 无建立连接的延迟 不限制发送速率(不进行拥塞控制和流量控制) 发送时间可控 报头开销小,why is there a UDP?,UDP适合的
21、应用: 容忍丢包但对延迟敏感的应用:如流媒体 以单次请求/响应为主的应用:如DNS若应用要求基于UDP进行可靠传输: 由应用层实现可靠性,Transport Layer,3-26,Chapter 3 outline,3.1 Transport-layer services 3.2 Multiplexing and demultiplexing 3.3 Connectionless transport: UDP 3.4 Principles of reliable data transfer,3.5 Connection-oriented transport: TCP segment struc
22、ture reliable data transfer flow control connection management 3.6 Principles of congestion control 3.7 TCP congestion control,Transport Layer,3-27,可靠数据传输原理,服务抽象:数据通过一条可靠信道传输,数据不会有比特损坏或丢失,并按照发送的顺序被接收。,Transport Layer,3-28,可靠数据传输原理,服务抽象:数据通过一条可靠信道传输,数据不会有比特损坏或丢失,并按照发送的顺序被接收。,Transport Layer,3-29,可靠数据
23、传输原理,服务抽象:数据通过一条可靠信道传输,数据不会有比特损坏或丢失,并按照发送的顺序被接收。,不可靠信道的特性决定了可靠数据传输协议(rdt)的复杂性。,Transport Layer,3-30,3.4.1 构造可靠数据传输协议,send side,receive side,Transport Layer,3-31,getting started,我们将: 增量地开发可靠数据传输协议(rdt)的发送方和接收方 只考虑单向数据传输,但控制信息可以双向传输 使用有限状态机(FSM)来描述发送方和接收方,event causing state transition,actions taken o
24、n state transition,state: when in this “state” next state uniquely determined by next event,Transport Layer,3-32,Rdt1.0: 可靠信道上的可靠传输,下层信道是完全可靠的(理想情况) 没有比特错误,没有分组丢失 发送能力 接收能力 发送方和接收方使用各自的FSM: 发送方:从上层接收数据,封装成分组送入下层信道 接收方:从下层信道接收分组,取出数据交给上层,Wait for call from above,packet = make_pkt(data) udt_send(packe
25、t),rdt_send(data),extract (packet,data) deliver_data(data),Wait for call from below,rdt_rcv(packet),sender,receiver,Transport Layer,3-33,Rdt2.0: 可能产生比特错误的下层信道,下层信道可能使分组中的比特产生错误(比特翻转) 可以通过某种检错码(如checksum)检测比特错误问题:如何从错误中恢复? 肯定确认(ACK): 接收方显式地告诉发送方,收到的分组正确 否定确认(NAK): 接收方显式地告诉发送方,收到的分组有错 发送方收到NAK后重传出错的分组
26、rdt2.0中需要三种新的机制: 接收方检错 接收方反馈 发送方重传分组,Transport Layer,3-34,rdt2.0: FSM specification,等待上 层调用,snkpkt = make_pkt(data, checksum) udt_send(sndpkt),extract(rcvpkt,data) deliver_data(data) udt_send(ACK),rdt_rcv(rcvpkt) & notcorrupt(rcvpkt),rdt_rcv(rcvpkt) & isACK(rcvpkt),udt_send(sndpkt),rdt_rcv(rcvpkt) &
27、isNAK(rcvpkt),sender,receiver,rdt_send(data),L,发送方FSM中增加了一个状态:等待反馈发送方依据收到的确认类型决定采取什么动作,接收方根据收到的分组正确与否采取不同的动作,Transport Layer,3-35,rdt2.0: operation with no errors,Wait for call from above,snkpkt = make_pkt(data, checksum) udt_send(sndpkt),extract(rcvpkt,data) deliver_data(data) udt_send(ACK),rdt_rcv
28、(rcvpkt) & notcorrupt(rcvpkt),rdt_rcv(rcvpkt) & isACK(rcvpkt),udt_send(sndpkt),rdt_rcv(rcvpkt) &isNAK(rcvpkt),Wait for call from below,rdt_send(data),L,Transport Layer,3-36,rdt2.0: error scenario,Wait for call from above,snkpkt = make_pkt(data, checksum) udt_send(sndpkt),extract(rcvpkt,data) deliver
29、_data(data) udt_send(ACK),rdt_rcv(rcvpkt) & notcorrupt(rcvpkt),rdt_rcv(rcvpkt) & isACK(rcvpkt),udt_send(sndpkt),rdt_rcv(rcvpkt) &isNAK(rcvpkt),Wait for call from below,rdt_send(data),L,Transport Layer,3-37,rdt2.0 has a fatal flaw!,如果ACK或NAK出错会如何? 发送方不清楚接收方发生了什么! 处理方法:令发送方收到出错的确认后,重传该分组 问题:可能在接收端产生冗余
30、分组,如何处理冗余问题? 发送方给每个分组添加一个序号 接收方根据序号检测冗余的分组,并丢弃(不会交付给上层) 分组序号的长度: 只需1个比特,用于区分是新的分组还是重发的分组,Transport Layer,3-38,rdt2.1: 发送方,处理出错的ACK/NAK,Wait for call 0 from above,sndpkt = make_pkt(0, data, checksum) udt_send(sndpkt),rdt_send(data),udt_send(sndpkt),rdt_rcv(rcvpkt) & ( corrupt(rcvpkt) | isNAK(rcvpkt)
31、),sndpkt = make_pkt(1, data, checksum) udt_send(sndpkt),rdt_send(data),rdt_rcv(rcvpkt) & notcorrupt(rcvpkt) & isACK(rcvpkt),udt_send(sndpkt),rdt_rcv(rcvpkt) & ( corrupt(rcvpkt) | isNAK(rcvpkt) ),rdt_rcv(rcvpkt) & notcorrupt(rcvpkt) & isACK(rcvpkt),L,L,收到出错的 分组或NAK,重发分组,收到ACK,转移状态,收到出错的分组或NAK,重发分组,收到
32、ACK,转移状态,Transport Layer,3-39,发送方FSM:rdt2.0 vs Rdt2.1,Rdt2.0 构造分组:不加序号 等待反馈: 收到NAK,重发分组 收到ACK,转移状态,Rdt 2.1 构造分组:加入序号 等待反馈: 收到NAK或者出错的反馈,重发分组 收到ACK,转移状态,Transport Layer,3-40,rdt2.1: 接收方,处理出错的ACK/NAK,sndpkt = make_pkt(NAK, chksum) udt_send(sndpkt),rdt_rcv(rcvpkt) & not corrupt(rcvpkt) &has_seq0(rcvpkt
33、),rdt_rcv(rcvpkt) & notcorrupt(rcvpkt) & has_seq1(rcvpkt),extract(rcvpkt,data) deliver_data(data) sndpkt = make_pkt(ACK, chksum) udt_send(sndpkt),rdt_rcv(rcvpkt) & notcorrupt(rcvpkt) & has_seq0(rcvpkt),extract(rcvpkt,data) deliver_data(data) sndpkt = make_pkt(ACK, chksum) udt_send(sndpkt),rdt_rcv(rc
34、vpkt) & (corrupt(rcvpkt),sndpkt = make_pkt(ACK, chksum) udt_send(sndpkt),rdt_rcv(rcvpkt) & not corrupt(rcvpkt) &has_seq1(rcvpkt),rdt_rcv(rcvpkt) & (corrupt(rcvpkt),sndpkt = make_pkt(ACK, chksum) udt_send(sndpkt),sndpkt = make_pkt(NAK, chksum) udt_send(sndpkt),收到出错的分组,发送NAK,正确收到序号为0的分组, 发送ACK,转移状态,正确
35、收到序号为0的分组 (冗余),发送ACK,正确收到序号为1的分组,发送ACK 转移状态,正确收到序号为1的分组 (冗余),发送ACK,收到出错的分组,发送NAK,Transport Layer,3-41,接收方FSM:rdt2.0 vs rdt2.1,Rdt2.0: 收到出错的分组:发送NAK 收到正确的分组:交付数据,发送ACK,Rdt2.1: 收到出错的分组:发送NAK 收到冗余的分组:发送ACK,不交付数据,不转移状态 收到正确的新分组:交付数据,发送ACK,转移状态,rdt2.2: 不使用NAK的协议,接收方: 只对正确接收的分组发送ACK,ACK携带所确认分组的序号 若收到出错的分组
36、,重发最近一次的ACK,发送方的处理: 收到期待序号的ACK:允许发送下一个分组 其它情况:重发当前分组接收方的处理: 收到期待序号(#n)的分组:发送ACK n 其它情况:重发最近一次的ACK,Transport Layer,3-42,rdt2.1也可以不用NAK,只用ACK,Transport Layer,3-43,rdt2.2: sender, receiver fragments,sndpkt = make_pkt(0, data, checksum) udt_send(sndpkt),rdt_send(data),udt_send(sndpkt),rdt_rcv(rcvpkt) &
37、( corrupt(rcvpkt) |isACK(rcvpkt,1) ),rdt_rcv(rcvpkt) & notcorrupt(rcvpkt) & isACK(rcvpkt,0),sender FSM fragment,rdt_rcv(rcvpkt) & notcorrupt(rcvpkt) & has_seq1(rcvpkt),extract(rcvpkt,data) deliver_data(data) sndpkt = make_pkt(ACK1, chksum) udt_send(sndpkt),rdt_rcv(rcvpkt) & (corrupt(rcvpkt) |has_seq
38、1(rcvpkt),udt_send(sndpkt),receiver FSM fragment,L,正确收到序号为1的分组,发送ACK1,不是期待接收的序号为 0的分组,重发ACK1,不是期待的ACK0,重发当前分组,收到期待的ACK0,转移到下一个状态,Transport Layer,3-44,rdt3.0: 可能产生比特错误和丢包的下层信道,增加新的假设: 下层信道可能丢包(包括数据及ACK)需要两项新技术: 检测丢包 从丢包中恢复,方法: 检测丢包: 若发送方在“合理的”时间内未收到ACK,认为丢包(需要定时器) 从丢包中恢复: 发送方重发当前分组 接收方使用分组序号检测重复分组,Tr
39、ansport Layer,3-45,发送方FSM:Rdt2.2 vs Rdt3.0,Rdt2.2: 发送分组,等待确认 收到期待序号的ACK,转移状态 不是期待序号的ACK,重发分组,Rdt3.0: 发送分组后启动一个定时器 收到期待序号的ACK,终止定时器,转移状态 收到不是期待序号的ACK,不做处理 定时器超时后,重发分组,Transport Layer,3-46,rdt3.0 sender,sndpkt = make_pkt(0, data, checksum) udt_send(sndpkt) start_timer,rdt_send(data),rdt_rcv(rcvpkt) &
40、( corrupt(rcvpkt) | isACK(rcvpkt,1) ),sndpkt = make_pkt(1, data, checksum) udt_send(sndpkt) start_timer,rdt_send(data),rdt_rcv(rcvpkt) & notcorrupt(rcvpkt) & isACK(rcvpkt,0),rdt_rcv(rcvpkt) & ( corrupt(rcvpkt) | isACK(rcvpkt,0) ),rdt_rcv(rcvpkt) & notcorrupt(rcvpkt) & isACK(rcvpkt,1),stop_timer,stop
41、_timer,udt_send(sndpkt) start_timer,timeout,udt_send(sndpkt) start_timer,timeout,rdt_rcv(rcvpkt),L,rdt_rcv(rcvpkt),L,L,L,不是期待的ACK0, 不做处理,超时重传,是期待的ACK0, 终止定时 器,转移状态,不是期待的ACK1, 不做处理,超时重传,是期待的 ACK1, 终止定时 器,转移状态,在等待上层调用时,对收到的分组不处理,在等待上层调用时,对收到的分组不处理,接收方FSM:Rdt2.2 vs Rdt3.0,Rdt3.0新增的事件 数据分组丢失: 接收方感知不到丢包,
42、该事件对接收方FSM无影响 ACK丢失,过早超时: (发送方重发)接收方收到重复的数据分组 接收方利用序号检测重复分组,重发前一次ACK,Rdt2.2 ACK损坏: (发送方重发)接收方收到重复的数据分组 接收方利用序号检测重复分组,重发前一次ACKRdt2.2的接收方FSM不加修改就可以用于rdt3.0的接收方。,Transport Layer,3-47,Transport Layer,3-48,rdt3.0 in action,Transport Layer,3-49,rdt3.0 in action,Rdt协议小结,Rdt 1.0 理想信道 发送方:只管发送 接收方:只管接收 Rdt 2
43、.0 数据可能出错 引入检错、反馈(ACK 和NAK)和重传机制,Rdt 2.1 反馈也可能出错 若反馈出错,重传分组 引入分组序号,用于区分重复分组 Rdt 2.2 取消NAK ACK中引入分组序号 Rdt 3.0 可能丢包 引入定时器,超时重传,Transport Layer,3-50,Transport Layer,3-51,rdt3.0:停-等协议,first packet bit transmitted, t = 0,sender,receiver,RTT,last packet bit transmitted, t = L / R,first packet bit arrives,
44、last packet bit arrives, send ACK,ACK arrives, send next packet, t = RTT + L / R,Transport Layer,3-52,rdt3.0的性能,example: 1 Gbps link, 30 ms RTT, 1KB packet:,T,transmit,=,8kb/pkt,10*9 b/sec,= 8 microsec,U sender: utilization fraction of time sender busy sending,L (packet length in bits),R (transmissi
45、on rate, bps),=,1KB pkt every 30 msec - 33kB/sec thruput over 1 Gbps link network protocol limits use of physical resources!,rdt3.0是一个正确的协议,但性能不佳!,Transport Layer,3-53,流水线:提高链路利用率,first packet bit transmitted, t = 0,sender,receiver,RTT,last bit transmitted, t = L / R,first packet bit arrives,last pa
46、cket bit arrives, send ACK,ACK arrives, send next packet, t = RTT + L / R,last bit of 2nd packet arrives, send ACK,last bit of 3rd packet arrives, send ACK,Increase utilization by a factor of 3!,Transport Layer,3-54,3.4.2 流水线可靠数据传输协议,流水线协议: 允许发送方有多个已发送、未确认的分组 分组的序号范围应扩大(停等协议只使用1比特序号) 发送端和接收端可能需要缓存多个
47、分组(停等协议中,发送端缓存一个分组,接收端不缓存),两种基本的流水线协议: go-Back-N, selective repeat,Transport Layer,3-55,Go-Back-N,Sender: 假设最多允许N个已发送、未确认的分组 发送端看到的序号空间(由序号长度决定)划分为以下4个区域:,已发送未确认序号 + 未发送可用序号 = 发送窗口(包含N个序号) Ack分组携带所确认的分组的序号 使用累积确认: 若ACK包含序号q,表明“序号至q的分组均正确收到” 若发送方收到ACK q,整体滑动发送窗口,使基序号= q+1 发送方只对基序号分组使用一个定时器 超时:发送方重传发送
48、窗口中从基序号开始的所有分组,Transport Layer,3-56,GBN: 接收方FSM,只使用ACK: 仅对正确收到的、序号连续的一系列分组中的最高序号进行确认(累积确认的要求) 收到失序的分组: 丢弃(不在接收端缓存),意味着接收方只能按顺序接收分组 重发前一次的ack(已正确收到、序号连续的一系列分组中的最高序号),Wait,udt_send(sndpkt),default,rdt_rcv(rcvpkt)& notcurrupt(rcvpkt)& hasseqnum(rcvpkt,expectedseqnum),extract(rcvpkt,data) deliver_data(data) sndpkt = make_pkt(expectedseqnum,ACK,chksum) udt_send(sndpkt) expectedseqnum+,
copyright@ 2008-2019 麦多课文库(www.mydoc123.com)网站版权所有
备案/许可证编号:苏ICP备17064731号-1