图解TCP/IP
计算机使用模式的演变:20世纪50年代 批处理时代20世纪60年代 分时系统时代20世纪70年代 计算机间通信时代20世纪80年代 计算机网络时代20世纪90年代 互联网普及时代2000年以互联网为中心的时代2010年无论何时何地地一切皆TCP/IP的网络时代在计算机网络与信息通信领域,人们经常提及“协议”。简单来说。协议就是计算机与计算机之间通过网络实现通信时事先达成的一种“约定”。这种“约定”使那些由不同厂商的设备、不同的CPU以及不同的操作系统组成的计算机之间,只要遵循相同的协议就能实现通信。换句话说,协议就是计算机之间的通信语言,只有支持相同的协议,计算机之间才能相互通信。计算机通信也会在每一个分组中附加上源主机地址和目标主机地址送给通信线路。这些发送端地址、接收端地址以及分组序号写入的部分称为“报文首部”。TCP/IP协议并非ISO(国际标准化组织)所制定的某种国际标准,而是由IETF(Internet Engineering Task Force国际互联网工程任务组)所建议的、致力于推进器标准化作业的一种协议。OSI参考模型应用层:针对特定应用的协议。以电子邮件为例,用户A在主机A上新建一封电子邮件,指定收件人为B,并输入邮件内容为“早上好”。应用层协议会在所要传递数据的前端附加一个首部(标签)信息,该首部标明了邮件内容为“早上好”和收件人为B。表示层:设备固有数据格式和网络标准数据格式的转换。用户A和用户B使用的邮件客户端一致,便能够顺利收取和阅读邮件,不一致时表示层就发挥作用了:将数据从“某个计算机特定的数据格式”转换为“网络通用的标准数据格式”后再发送出去,接收端也进行相应处理。表示层与表示层之间为了识别编码格式也会附加首部信息,从而将实际传输的数据转交给下一层处理。会话层:通信管理。负责建立和断开通信连接(数据流动的逻辑通路)。管理传输层以下的分层。假定用户A新建了5封电子邮件准备发送给用户B,是建立一次连接一起发送,还是分别建立5次连接各自发送,都是会话层决定的,会话层和表示层一样,也会在数据前段附加首部或标签信息再转发给下一层。而这些首部或标签中记录着数据传送顺序的信息。传输层:管理两个节点之间的数据传输。负责可靠传输(确保数据被可靠传送到目标地址)。用主机A将“早上好”这一数据发送给主机B,期间可能因为某些原因导致数据损坏,主机B只收到“早上”,此时也会将这一事实告诉主机A,主机A得知情况会将后面的“好”重发给主机B。保证数据传输的可靠性是传输层的一个重要作用。为了确保可靠性,这一层所要传输的数据附加首部以识别这一分层的数据。然而,实际上将数据传输给对端的处理是由网络层来完成的。网络层:地址管理与路由选择。两端主机之间虽然有众多数据链路,但能够将数据从主机A送到主机B也都是网络层的功劳。相当于TCP/IP协议中的IP协议,网络层不能保证数据的可达性,所以需要传输层TCP协议确保可达性,所以TCP/IP协议实现了可靠传输。数据链路层:互连设备之间传送和识别数据帧。网络层负责将整个数据发送给最终目标地址,而数据链路层则只负责发送一个分段内的数据。物理层:以“0”、“1”代表电压的高低、灯光的闪灭。界定连接器和网线的规格。将数据的0、1转换为电压和脉冲光传输给物理的传输介质。计算机之间的网络连接通过电缆相互连接。任何一台计算机连接网络时,必须要使用网卡(网络适配器、NIC、LAN卡),中继器的作用是将电缆传过来的信号调整和放大再传给另一个电缆,可以完成不同媒介之间的连接工作。网桥是数据链路层面上连接两个网络的设备,提供的是传递数据帧的作用,并且还具备自学机制。路由器是在网络层面上(OSI七层模型网络层)连接两个网络、并对分组报文进行转发的设备。网桥是根据物理地址(MAC地址)进行处理,而路由器/3层交换机则是根据IP地址进行处理的。由此,TCP/IP中网络层的地址就成为了IP地址。对于并发访问量非常大的一个企业级Web站点,使用一台服务器不足以满足前端的访问需求,这时通常会架设多台服务器来分担。这些服务器的访问的入口地址通常只有一个,为了能通过同一个URL将前端访问分发到后台多个服务器上,可以将这些服务器的前端加一个负载均衡器。这种负载均衡器就是4-7层交换机的一种。网关是OSI参考模型中负责将从传输层到应用层的数据进行转换和转发的设备。在两个不能进行直接通信的协议之间进行翻译,最终实现两者的通信。非常典型的例子就是互联网邮件和手机邮件之间的转换服务。防火墙也是一款通过网关通信,针对不用应用提高安全性的产品。美国军方利用分组交换技术组件的ARPANET网络是互联网的鼻祖。而BSD UNIX操作系统实现了TCP/IP协议,随着UNIX系统的普及,TCP/IP协议开始盛行。TCP/IP可以单纯的指这两种协议,然而在很多情况下,它指的是包含HTTP、SMTP、FTP、TCP、UDP、IP、ARP等很多协议的网际协议族。发送数据包的过程,和上节OSI参考模型中介绍的差不多。数据链路层是由网络接口(以太网驱动)来处理的,它会改数据附加上以太网首部,以太网首部中包含接收端的MAC地址、发送端MAC地址以及标志以太网类型的以太网数据的协议。在以太网普及之初,一般多台终端使用同一根同轴电缆的共享介质型连接方式,访问控制一般以半双工通信为前提采用CSMA/CD方式。随着ATM交换技术的进步和CAT5 UTP电缆的普及很快发生了变化,逐渐采用像非共享介质网络那样直接与交换机连接的方式。网络层与数据链路层的关系某人要去一个很远的地方旅行,并计划先后乘坐飞机、火车、公交车到达目的地。旅行社不仅帮他预订好了飞机票和火车票,甚至还为他指定了一个详细的行程表,详细到几点几分需要乘坐飞机或火车都一目了然。机票和火车票只能够在某一限定区间内移动,此处的“区间内”就如同通信网络上的数据链路。这个区间内的出发地点和目的地点就如同某一个数据链路的源地址和目标地址等首部信息。整个行程表的作用就相当于网络层。DNS:将域名和IP地址相匹配。ARP:以目标IP地址为线索,用来定位下一个应该接受数据分包的网络设备对应的MAC地址。ARP只适用于IPv4,IPv6可以用ICMPv6替代ARP发送邻居探索消息。ICMP:在IP通信中如果某个IP包因为某种原因未能送达目标地址,那么这个具体的原因将由ICMP负责通知。DHCP:使用移动设备时,每移动到一个新地方,都要重新设置IP地址,为了实现自动设置IP地址、统一管理IP地址分配,就产生了DHCP协议。NAT:是用于在本地网络中使用私有地址,在连接互联网时转而使用全局IP地址的技术。IP隧道:IPv4和IPv6之间进行通信的技术就是IP隧道。TCP用于低速可靠传输UDP用于高速不可靠传输端口号就是用来识别同一台计算机中进行通信的不同应用程序,也被称为程序地址。TCP传输利用窗口控制提高速度,无需等到每次应答来进行下一次发送,而是有个窗口进行缓冲,来提高吞吐量。TCP拥塞控制,利用拥塞窗口来调节发送的数据量,拥塞时减小窗口,流畅是增大窗口来控制吞吐量。我们日常网络访问的http用的是tcp ,那还是看一下这个过程吧tcp可以提供全双工的数据流传输服务,全双工说白了,就是同一时间A可以发信息给B , B也可以发消息给A ,俩人同时都可以给对方发消息;半双工就是某个时间段A可以发给B ,但B不能给A ,换个时间段,就反过来了。这个过程理解起来,就像两人在喊话:A:喂,有人吗,我想建立连接B:有哇,你建立吧,等你吆A:好哒,我来啦然后俩人就建立连接了...一定要三次握手么,两次行不行?这么一个场景:A->B: 洞幺洞幺,我是洞拐,收到请回复。B->A: 洞拐洞拐,洞幺收到。请问根据以上对话判断:1、B是否能收到A的信息? (答案是肯定的)2、A是否能收到B的信息? (你猜?)tcp的核心思想是保证数据可靠传输,如果2次,显然不行,但3次就一定行么?未必,可能第三次的时候网络中断了,然后A就认为B收到了,然后一通发消息,其实B没收到,但这是无法完全保证的。无论握手多少次都不能满足传输的绝对可靠,为了效率跟相对可靠而看,3次刚刚好,所以就3次了(正好AB相互确认了一次)。举个栗子:把客户端比作男孩,服务器比作女孩。通过他们的分手来说明“四次挥手”过程:"第一次挥手" :日久见人心,男孩发现女孩变成了自己讨厌的样子,忍无可忍,于是决定分手,随即写了一封信告诉女孩。“第二次挥手” :女孩收到信之后,知道了男孩要和自己分手,怒火中烧,心中暗骂:你算什么东西,当初你可不是这个样子的!于是立马给男孩写了一封回信:分手就分手,给我点时间,我要把你的东西整理好,全部还给你!男孩收到女孩的第一封信之后,明白了女孩知道自己要和她分手。随后等待女孩把自己的东西收拾好。“第三次挥手” :过了几天,女孩把男孩送的东西都整理好了,于是再次写信给男孩:你的东西我整理好了,快把它们拿走,从此你我恩断义绝!“第四次挥手” :男孩收到女孩第二封信之后,知道了女孩收拾好东西了,可以正式分手了,于是再次写信告诉女孩:我知道了,这就去拿回来!为什么连接的时候是三次握手,关闭的时候却是四次握手?答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文 。其中ACK报文是用来应答的, SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET ,所以只能先回复一个ACK报文 ,告诉Client端 ,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文 ,因此不能一起发送。故需要四步握手。静态路由是指事先设置好路由器和主机中并将路由信息固定的一种方法。缺点是某个路由器发生故障,基本上无法自动绕过发生故障的节点,只有在管理员手工设置以后才能恢复正常。动态路由是管理员先设置好路由协议,其设定过程的复杂程度与具体要设置路由协议的类型有直接关系。在路由器个数较多的网络,采用动态路由显然能够减轻管理员负担。网络发生故障,只要有一个可绕的其他路径,数据包会自动选择这个路径,但路由器需要定期相互交换必要的路由控制信息,会增加一定程度的负荷。根据路由控制范围分为IGP(内部网关协议)和EGP(外部网关协议)路由算法分为距离向量算法和链路状态算法距离向量算法:通过距离与方向确定通往目标网络的路径链路状态算法:链路状态中路由器知道网络的连接状态,并根据链路信息确定通往目标网络的路径。IGP包含RIP、RIP2、OSPFEGP包含EGP、BGPRIP是距离向量型的一种路由协议,广泛应用于LANRIP2是RIP的第二版。新增以下特点:使用多播、支持子网掩码、路由选择域、外部路由标志、身份验证密钥OSPF是一种链路状态型路由协议。在RIP和OSPF中利用IP的网络地址部分进行着路由控制,然而BGP则需要放眼整个互联网进行路由控制。BGP的最终路由控制表有网络地址和下一站的路由器组来表示,不过它会根据所要经过的AS个数进行路由控制。有了AS编号的域,就相当于有了自己一个独立的“国家”。AS的代表可以决定AS内部的网络运营和相关政策。与其他AS相连的时候,可以像一位“外交官”一样签署合约再进行连接。正是有了这些不同地区的AS通过签约的相互连接,才有了今天全球范围内的互联网。转发IP数据包的过程中除了使用路由技术外,还在使用标记交换技术。最有代表性的就是多协议标记交换技术(MPLS)。MPLS的标记不像MAC地址直接对应到硬件设备。因此,MPLS不需要具备以外网或ATM等数据链路层协议的作用,而只需要关注它与下面一层IP层之间的功能和协议即可。MPLS优点:1.转发速度快2.利用标记生成虚拟路径,并在它的上面实现IP等数据包的通信。

TCP/IP模型的分解示意图
如图

TCP/IP协议结构分布图
TCP/IP协议并不完全符合OSI的七层参考模型。传统的开放式系统互连参考模型,是一种通信协议的7层抽象的参考模型,其中每一层执行某一特定任务。该模型的目的是使各种硬件在相同的层次上相互通信。这7层是:物理层、数据链路层、网路层、传输层、话路层、表示层和应用层。 而TCP/IP通讯协议采用了4层的层级结构,每一层都呼叫它的下一层所提供的网络来完成自己的需求。这4层分别为:●应用层:应用程序间沟通的层,如简单电子邮件传输(SMTP)、文件传输协议(FTP)、网络远程访问协议(Telnet)等。●传输层:在此层中,它提供了节点间的数据传送服务,如传输控制协议(TCP)、用户数据报协议(UDP)等,TCP和UDP给数据包加入传输数据并把它传输到下一层中,这一层负责传送数据,并且确定数据已被送达并接收。●互连网络层:负责提供基本的数据封包传送功能,让每一块数据包都能够到达目的主机(但不检查是否被正确接收),如网际协议(IP)。 ●网络接口层:对实际的网络媒体的管理,定义如何使用实际网络(如Ethernet、Serial Line等)来传送数据。
1、TCP/IP协议栈 四层模型TCP/IP这个协议遵守一个四层的模型概念:应用层、传输层、互联层和网络接口层。网络接口层模型的基层是网络接口层。负责数据帧的发送和接收,帧是独立的网络信息传输单元。网络接口层将帧放在网上,或从网上把帧取下来。互联层互联协议将数据包封装成internet数据报,并运行必要的路由算法。这里有四个互联协议:网际协议IP:负责在主机和网络之间寻址和路由数据包。地址解析协议ARP:获得同一物理网络中的硬件主机地址。网际控制消息协议ICMP:发送消息,并报告有关数据包的传送错误。互联组管理协议IGMP:被IP主机拿来向本地多路广播路由器报告主机组成员。传输层传输协议在计算机之间提供通信会话。传输协议的选择根据数据传输方式而定。两个传输协议:传输控制协议TCP:为应用程序提供可靠的通信连接。适合于一次传输大批数据的情况。并适用于要求得到响应的应用程序。用户数据报协议UDP:提供了无连接通信,且不对传送包进行可靠的保证。适合于一次传输小量数据,可靠性则由应用层来负责。应用层应用程序通过这一层访问网络。网络接口技术IP使用网络设备接口规范NDIS向网络接口层提交帧。IP支持广域网和本地网接口技术。串行线路协议 TCP/IPG一般通过internet串行线路协议SLIP或点对点协议PPP在串行线上进行数据传送。(是不是我们平时把它称之为异步通信,对于要拿LINUX提供建立远程连接的朋友应该多研究一下这方面的知识)?

传输层TCP协议连接的建立和断开
什么是TCP呢?由三个单词组成的Transport Control Protocol,字面理解是传输控制协议,可以理解为比特同学要想在网络泳池里游泳,那么他必须学习传输层控制技能,并且要掌握相应的动作——协议,他才能在畅游世界网络这个超大型游泳池。TCP:一个传输层协议,提供Host-To-Host的可靠传输,支持全双工,是一个面向连接的协议。TCP工作在传输层,它的上层是应用层,应用就是人们常用的微信、抖音、王者荣耀等服务工作的协议。两台不同的设备使用微信聊天,发送语音,需要实现Host-To-Host的数据通信,那么就可以直接调用TCP协议进行。调用TCP通信时需要指定通信的端口,不同的端口对应不同应用,不同IP对应不同的主机,也就是不同的设备。这就涉及到网络地址——IP地址,工作在网络层,当然TCP层只负责把对应的IP地址和端口传给网络层即可,具体业务由网络层来实现。互联网层,即Network Layer,提供地址和地址间的通信,只关注地址到地址Address-To-Address间通信,具体设备间通信由数据链路层实现,数据链路层关注MAC地址间通信,具体的物理设备,传输介质由物理层负责。以上就是TCP/IP协议常用的层级分割,最终目的就是为Host-To-Host服务,实现应用到应用的通信服务。什么是连接和会话呢?连接事需要通信双方相互配合来实现的,是双方达成的一种即时的状态约定,保证通信双方都在线,都有能力为接下来的数据传输做出尽快的响应,我们称之为连接。连接是网络行为状态的记录,既然连接需要双方共同努力,那么就需要双方都有一个对象来记忆当前传输的数据类型,对方的端口、已经传输了多少,效率怎么样等等一些关注点。那么与之相关联的另一个名词会话(Session),是什么意思呢,会话是应用的行为。大家每次用微信聊天时都会有一个窗口,用来发送信息,你来我往,这个窗口中会有很多条信息,我们称之为会话,当我们在会话进行中,连接一定是在通信状态的。聊一会,累了,退出微信了,但是一般我们不会删除我们的会话内容,这时会话还在,但是连接已经中断。双工/单工问题想想自己理解的是什么?单工:任何时间,数据只能单向发送,单工至少需要一条线路半全双工:某一时候可以双向发送数据,至少需要一条线路全双工:任何时刻都可以双向发送数据,大于一条线路这里线路不一定真实存在物理线路,可能采用模拟的形式实现TCP是一个全双工协议,数据任何时刻都可以双向发送,这说明服务器和客户端可以根据需要选择任意时刻发送和接收信息,所以呢都可以被称为主机(Host)可靠性的定义TCP可以提供可靠性,那么可靠性具体的实现方式是什么呢?可靠性指数据无损传输。发送主机按照顺序发送数据,数据通过网络传输,收不同网络条件限制,数据不会按照发送时的顺序到达接收方,这时我们就需要一种算法来保证接收方可以还原出发送方的顺序。这里还有一个概念叫多播,发送方同时发送给多个接收方信息,如果接收方中有一个接收到了这条信息,我们的可靠性就必须保证其他接收方也必须接收到相同的信息,这里我们不讨论多播。TCP的握手和挥手TCP是一个面向连接的连接的协议,握手是建立连接的过程,挥手是断开连接的过程。TCP的基本操作以上三种操作以后,另一方必须立即给发起方返回一个ACK(Ackknowledgement),这是TCP保证可靠性的要求。如果一方不回复发送方ACK,发送方则认为接收方没有收到信息,会重新发送。建立连接的过程-三次握手三次握手的形成和TCP要求每次发送方发送信息以后,接收方必须返回ACK确认有直接的关系上图描述了TCP建立连接的过程,分为6步:TCP建立连接的过程如上,那么为什么是三次呢?第二步服务端做准备,因为是首次收到发送数据请求,无需处理,可以立刻进入数据交互状态,所以可以立刻发送给客户端SYN,告诉客户端,我已准备好,所以第三步和第四步可以合并为一次握手——ACK-SYN,然后客户端回应ACK,连接建立完成以上就是三次握手了具体在数据交互过程,ACK和SYN等需要用标识位来标记,在实际应用中,我们一般使用1来表示开启,0表示关闭。那么四次挥手为什么是四次呢,主要是因为,挥手时服务端收到FIN以后,不能马上回复FIN,因为自身还有任务没有处理完,所以上面所说的6步中,第3、4步就不能一起回复,只能先回复ACK,等自身任务处理完毕,才能告诉客户端,我已经准备好,可以关闭连接,这样就需要4次数据交互,如下图:

如何实现TCP和UDP传输
首先我们来看一下什么是TCP和UDP。 什么是TCP?TCP:Transmission Control Protocol 传输控制协议TCP是一种面向连接(连接导向)的、可靠的、基于字节流的运输层(Transport layer)通信协议,由IETF的RFC 793说明(specified)。在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能。应用层向TCP层发送用于网间传输的、用8位字节表示的数据流,然后TCP把数据流分割成适当长度的报文段(通常受该计算机连接的网络的数据链路层的最大传送单元(MTU)的限制)。之后TCP把结果包传给IP层,由它来通过网络将包传送给接收端实体的TCP层。TCP为了保证不发生丢包,就给每个字节一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的字节发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据(假设丢失了)将会被重传。TCP用一个校验和函数来检验数据是否有错误;在发送和接收时都要计算校验和。首先,TCP建立连接之后,通信双方都同时可以进行数据的传输,其次,他是全双工的;在保证可靠性上,采用超时重传和捎带确认机制。在流量控制上,采用滑动窗口协议[1],协议中规定,对于窗口内未经确认的分组需要重传。在拥塞控制上,采用慢启动算法。什么是UDP?UDP 是User Datagram Protocol的简称, 中文名是用户数据包协议,是 OSI 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。它是IETF RFC 768是UDP的正式规范。在网络中它与TCP协议一样用于处理数据包。在OSI模型中,在第四层——传输层,处于IP协议的上一层。UDP有不提供数据报分组、组装和不能对数据包的排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。 UDP用来支持那些需要在计算机之间传输数据的网络应用。包括网络视频会议系统在内的众多的客户/服务器模式的网络应用都需要使用UDP协议。UDP协议从问世至今已经被使用了很多年,虽然其最初的光彩已经被一些类似协议所掩盖,但是即使是在今天,UDP仍然不失为一项非常实用和可行的网络传输层协议。与所熟知的TCP(传输控制协议)协议一样,UDP协议直接位于IP(网际协议)协议的顶层。根据OSI(开放系统互连)参考模型,UDP和TCP都属于传输层协议。UDP协议的主要作用是将网络数据流量压缩成数据报的形式。一个典型的数据报就是一个二进制数据的传输单位。每一个数据报的前8个字节用来包含报头信息,剩余字节则用来包含具体的传输数据。TCP和UDP在android中的使用和在Java里是完全一样的。首先我们看看TCP连接,下图为TCP连接的一个示意图:TCP传输原理是不是很好理解,这里就不多说了,直接看代码吧!实践出真知。TCP服务器端代码:try {Boolean endFlag = false;ServerSocket ss = new ServerSocket(12345);while (!endFlag) {// 等待客户端连接Socket s = ss.accept();BufferedReader input = new BufferedReader(newInputStreamReader(s.getInputStream()));//注意第二个参数据为true将会自动flush,否则需要需要手动操作output.flush()PrintWriter output = newPrintWriter(s.getOutputStream(),true);String message = input.readLine();Log.d("Tcp Demo", "message from Client:"+message);output.println("message received!");//output.flush();if("shutDown".equals(message)){endFlag=true;}s.close();}ss.close(); } catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}TCP客户端代码:try {Socket s = new Socket("localhost", 12345);// outgoing stream redirect to socketOutputStream out = s.getOutputStream();// 注意第二个参数据为true将会自动flush,否则需要需要手动操作out.flush()PrintWriter output = new PrintWriter(out, true);output.println("Hello IdeasAndroid!");BufferedReader input = new BufferedReader(newInputStreamReader(s.getInputStream()));// read line(s)String message = input.readLine();Log.d("Tcp Demo", "message From Server:" + message);s.close(); } catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}下面我们看看UDP:UDP传输原理UDP服务器端代码:// UDP服务器监听的端口Integer port = 12345;// 接收的字节大小,客户端发送的数据不能超过这个大小byte[] message = new byte[1024];try {// 建立Socket连接DatagramSocket datagramSocket = new DatagramSocket(port);DatagramPacket datagramPacket = new DatagramPacket(message,message.length);try {while (true) {// 准备接收数据datagramSocket.receive(datagramPacket);Log.d("UDP Demo", datagramPacket.getAddress().getHostAddress().toString()+ ":" + new String(datagramPacket.getData()));}} catch (IOException e) {e.printStackTrace();}} catch (SocketException e) {e.printStackTrace();}UDP客户端代码:public static void send(String message) {message = (message == null ? "Hello IdeasAndroid!" : message);int server_port = 12345;DatagramSocket s = null;try {s = new DatagramSocket();} catch (SocketException e) {e.printStackTrace();}InetAddress local = null;try {// 换成服务器端IPlocal = InetAddress.getByName("localhost");} catch (UnknownHostException e) {e.printStackTrace();}int msg_length = message.length();byte[] messagemessageByte = message.getBytes();DatagramPacket p = new DatagramPacket(messageByte, msg_length, local,server_port);try {s.send(p);} catch (IOException e) {e.printStackTrace();}} 代码中需要注意的地方已做了注释,希望本文对您有所帮助!

本文由 在线网速测试 整理编辑,转载请注明出处。