TCP 核心工作机制

TCP 的核心知识:如何保证传输可靠 + 如何提高传输效率

如何保证传输可靠:确认应答机制 + 超时重传机制

如何提高传输效率:滑动窗口机制、快速重传机制、流量控制机制、延时应答机制、捎带应答机制、拥塞控制机制

一、如何保证传输可靠

        TCP的可靠性主要是通过 确认应答 + 超时重传 来实现的。

1 确认应答机制

        先看发送方:在没有滑动窗口机制之前,发送方一次只能发送一段报文,且每次发送完后要等待接收方的ACK确认,只有在收到接收方的ACK确认应答后,才能将发送缓冲区里对应的数据释放掉,并开始发送第二段报文。如果在规定时间内未收到ACK确认,则尝试重传这段报文(超时重传机制)。

        再看接收方:接收方每次接收到报文后,都要给发送方返回一个确认应答报文ACK,告知对方已正确接收数据,期望下次收到报文段的起始序列号是ack。

        确认应答机制本质上是接收方对发送方报文中的seq进行确认,TCP是字节流传输协议,seq就代表数据,seq被确认就意味着数据被确认。只有确认应答机制 + 超时重传机制才能保证数据传输的可靠性,但数据传输效率比较低(RTT时间越长,传输效率越低)

2 超时重传机制

        TCP超时重传机制是针对确认应答阶段数据丢包的情况,TCP传输过程中,发送方发出的报文可能会丢失,接收方返回给对端的ACK报文也有可能丢失。无论是哪种丢包,发送方在发送完报文后如果在指定时间内(RTO,Retransmission Timeout 超时重传时间)未收到对端返回的ACK报文,就会重传这段报文。重传次数达到一定量时,如果还是无法收到ACK报文,发送方就会发送RST报文,要求重置连接,如果重置连接都失败那就彻底断开连接。

        不同类型的报文重传次数上限不同,请参考 Linux系统中跟TCP相关的系统配置项

        如果是最后一个数据包丢失(尾部丢包)了怎么办?还是等待RTO吗?针对尾部丢包问题,TCP专门引入了尾部丢失探测(TLP,Tail Loss Probe)机制,TLP是用快速重传方式取代超时重传(RTO)来处理尾包丢失现象。当最后一个数据包发出后,会增加一个尾部超时事件,超时时间是RTO的一半,这样就可以快速重传尾部数据包。

RTO随RTT动态变化。RTT越小,网络环境越好,RTO也随之变小。

如果超时重传的数据,因再次超时而重传时,超时重传时间将是先前值的两倍。

RTT(Round Trip Time):往返时长/往返时延,从报文发出到收到ACK确认应答所需时间。

SRTT(Smoothed Round Trip Time):平滑往返时长,对RTT的平均估算。每收到一次ACK确认应答,都会重新计算SRTT。

        接收方收到重复的报文怎么办?TCP接收数据时都先将数据写入到接收缓冲区(Receive Buffer),再根据seq对缓冲区数据进行排序,方便应用程序正确有序地读取数据。新接收到的数据在写入缓冲区后,自然也要根据seq排序,这时就很容易判断出这段数据是否重复,如果重复就直接丢弃,这种机制确保了应用层读取到的数据是有序且不重复的。

        超时重传存在的问题是,超时周期相对较长。

 3 连接管理机制

        通过三次握手建立连接,再通过四次挥手断开连接。

        参考文章 TCP三次握手、四次挥手及状态转换详解

二、如何提高传输效率

        TCP为了能最大限度的提高传输效率,分别从三方面对传输过程进行优化

  • 提高发送方的发送量(发送速率),如滑动窗口机制;
  • 提高接收方的接收能力(对方是否能承受大的数据量),如流量控制机制、延时应答机制;
  • 提高网络的转发能力(网络是否能转发大的数据量),如拥塞控制机制。

4 滑动窗口机制

4.1 为何要引入窗口概念?

        在没有引入窗口概念之前,确认应答机制中一次只能发送一条报文段,只有等被ACK确认应答后才能发送另一段报文。这传输效率着实有点慢,当网络环境不佳时,效率还会更慢。如何提高传输效率呢?有没有可能提高TCP的发送量呢,能否允许它先一次发送多条报文,然后再等ACK确认应答,先把发送量提起来再说。TCP这才引入了窗口概念,数据发送量以窗口大小来衡量。即使在RTT较长的情况下,也不会降低传输效率。

        在学习窗口之前,我们先简单了解下什么是缓冲区。

4.2 什么是缓冲区?

  • 缓冲区是TCP在操作系统中开辟的一块缓存空间,用于缓存将要发送和接收的数据;
  • TCP有两个缓冲区,分别是发送缓冲区接收缓冲区
  • 发送缓冲区和接收缓冲区都是环形队列
  • 应用层调用send函数将数据写入发送缓冲区,TCP从发送缓冲区获取数据并发送;
  • 网络层递交给TCP的数据最终被存放到接收缓冲区,应用层调用recv函数将数据从接收缓冲区读出。

4.3 什么是窗口?

        窗口分“发送窗口(swnd)”和“接收窗口(rwnd),首先它俩针对的缓冲区有所不同,发送窗口针对的是发送缓冲区,而接收窗口针对的是接收缓冲区。其次,发送方发送窗口的大小由接收方接收窗口的大小决定,但并不意味着两者就完全相等,因为有网络延迟,所以接收窗口大小一般约等于或稍大于发送窗口大小。还需注意的是,窗口大小并不代表缓冲区的大小

        接收窗口(大小)就是我们通常讲的窗口(大小),如:“A端窗口还是1M,让B端发送慢点”,这里的窗口指的就是A端的接收窗口大小,接收窗口对应TCP报头中的Window字段,表示接收方还剩多少接收缓冲区可用于接收数据。

        发送窗口(大小)指的是发送缓冲区中“已发送但未收到ACK确认”和“可以发送但还未发送”两块缓冲区的组成部分。这两部分的数据无需TCP确认就可直接推送给网络层。

        “已发送但未收到ACK确认”很好理解,就是已发送的报文在未等到确认应答ACK返回之前,必须保留在发送缓冲区中,如果在规定时间(RTO)内收到了ACK报文,就将数据从缓存区清除,否则重传报文。

        “可以发送但还未发送”指的是“可以发送但还没来得及发送,且总大小在接收方窗口大小范围之内”。

        注意:窗口是会动态变化的,可大可小,并不是下图中画的那样只有20字节。更严格点讲,每个编号表示一个分组,而每个分组对应的都是一个字节流,大小刚好是一个MSS。

4.4 引入滑动窗口机制 

        下面图中,如果32 ~ 45字节的数据状态不变,46 ~ 51字节的数据也已成功发送且未收到ACK确认,那么此时发送方的可用窗口就是0,在未收到新的ACK确认应答前无法继续发送数据。 

        如果32 ~ 45 字节中前一部分数据收到了ACK确认应答以后怎么办呢?总不能等这个窗口中的所有数据都被ACK确认应答后才换另一个窗口吧?这不是换汤不换药吗,TCP发送方还是要会花很长时间等待确认。然后,TCP就又引入了滑动窗口机制,让窗口动态滑动起来不就好了吗,前面已被ACK确认的数据我就释放掉,将窗口向右滑动,新进入窗口的数据开始发送,就这样边确认边滑动边发送,这不就提高了传输效率嘛。

        滑动窗口允许窗口内的报文数据,不需要等前一个报文段被ACK确认应答,就可以直接交给网络层进行传输,已被确认的数据会被窗口释放掉(还在缓冲区中,只是不在窗口内),窗口也随之向右移动,这样可大大提高TCP发送方的数据发送量。

4.5 发送方滑动窗口(四部分)

        如下图,当32 ~ 36字节的数据收到ACK确认应答后,如果发送窗口大小不变,则将窗口往右滑动5个字节,此时发送窗口就变成了由37 ~ 56字节组成的缓冲区了,后续就可以继续发送52 ~ 56字节之间的数据了。

发送方滑动窗口由以下四部分组成:

  • SND.WND:发送窗口大小(由接收窗口Window大小决定);
  • SND.UNA:是一个绝对指针,指向的是#2已发送但未收到ACK确认应答内容的第一个字节数据所对应的序列号;
  • SND.NXT:是一个绝对指针,指向的是#3可以发送但未发送内容的第一个字节数据所对应的序列号;
  • 是一个相对指针,SND.UNA + SND.WND,指向的是#4未发送且不能发送内容的第一个字节数据对应的序列号。

可用窗口大小 = SND.WND -(SND.NXT - SND.UNA)

4.6 接收方滑动窗口(三部分)

  • RCV.WND:接收窗口大小,会赋值给Window并发送给发送方
  • RCV.NXT:是一个绝对指针,指向的是期望发送方下次发送来的数据的起始序列号,即ack值
  • 是一个相对指针,RCV.NXT + RCV.WND,指向的是#4未收到且不可以接收的第一个字节数据对应的序列号。

5 快速重传

        快速重传机制可以理解成“发送方根据接收方返回的ACK报文预测发生了丢包,为什么是预测发生了丢包?因为发送方一次可能发送多个甚至多组数据包,这些数据包一旦被扔到网络中,可能会通过任何网络路径到达接收方,这就有可能发生seq较大的数据包先到达先被ACK,而seq较小的数据包后到达后被ACK,就是我们通常说的接收乱序。seq较小的数据包在未被ACK前,可能并未真正丢包,只是延迟时间较长而已。当发送方收到3次重复的较大seq数据包的ACK确认应答时,为了提高数据重传效率,发送方会假设或预测前面的数据包发生丢包,在未被确认真正丢包前就会重传这些数据包,所以快速重传是一种预测发生丢包的重传机制。

        乱序:指数据包在接收方的接收顺序与发送方的发送顺序不一致。

        乱序度:指在发生乱序,且丢失数据未被重传前,两个不连续数据包的最大序号差值。

5.1 快速重传机制

        引入滑动窗口机制后,发送方一次可发送多条报文,但又会面临一个新的问题,如果发出的多条报文中丢失了好几条(乱序)怎么办,干等着超时重传吗?等一个数据包重传完再判断另一个数据包是否丢失?然后再继续重传吗?这种重传效率显然比较低,所以TCP就引入了快速重传机制,可大大提高重传速率。

        快速重传(Fast Retransmit)机制,本质还是为了提高传输效率,它不以时间为驱动,而是以数据驱动重传,在没有触发超时重传前,就已经触发发送方重传数据了。

        发送方利用滑动窗口机制一次发出了5条报文,如下图

  • 接收方收到seq1报文,返回ack2;
  • 接收方收到seq3报文,未收到seq2,还是返回ack2;
  • 接收方收到seq4和seq5报文,但还未收到seq2,最终还是返回ack2;
  • 发送方收到了3次重复的ack2,表明seq2丢失了,便立即重传丢失的seq2;
  • 接收方收到seq2报文,返回ack6。

        快速重传的工作方式是当发送方收到三次冗余的(不含第一次)重复的 ACK 报文后,在RTO生效前,立即重传预测丢失的数据包,这样就可以有效缩减重传时间。但这里面还存在效率的问题,如果发送方发出了6条或更多条报文,假设 seq2 和 seq3 都丢失了,发送方在收到3次冗余的ack2报文后,此时它首先能肯定的是seq2丢失了,但不确定seq2之后的数据有没有丢失,怎么办呢?只能先把seq2发出去再说,等收到后面的ack后再判读有没有其它数据丢失。假设当前通信网络环境不佳,发送方发送了很多条报文出去,丢包率为10%,发送方如果还是按照上面这种方式重传报文的话,其实效率也没提高多少。为了解决快重传的效率问题,于是就有了选择性确认SACK(Selective Acknowledgment),该参数位于TCP报头的Options,发送方可通过SACK值来判断哪部分数据丢失,有针对性地进行快重传,大大提高了重传效率。

5.2 SACK

        选择性确认(SACK,Selective Acknowledgment)用于数据重传机制,位于TCP报头的Options。接收方可通过SACK参数告知发送方我方收到了不连续的数据块(ack=200,SACK=300-400),发送方可根据此信息检查哪部分数据丢失(对方收到200字节数据,接收到了300-400段,说明200-299段丢失了)并重传丢失的数据。SACK主要解决重传哪些数据包问题。

        TCP三次握手过程中,双方会通过“SACK Permitted”来互相声明自己是否支持SACK,只有双方都支持SACK时,TCP才会使用SACK。Linux开启SACK的方法如下

#linux系统中可通过修改net.ipv4.tcp_sack来决定是否开启SACK,Linux 2.4后默认开启
[root@reader ~]# sysctl -a | grep net.ipv4.tcp_sack
net.ipv4.tcp_sack = 1
[root@reader ~]# find / -name *tcp_sack*
/proc/sys/net/ipv4/tcp_sack
[root@reader ~]# cat /proc/sys/net/ipv4/tcp_sack
1
[root@reader ~]# 

可以用echo或sysctl -w 来临时修改tcp_sack
也可以在系统配置文件 /etc/sysctl.conf 中,添加如下一行代码,永久修改 tcp_sack
net.ipv4.tcp_sack = <new_value>

当发送大量数据包时,如果出现了乱序现象,接收方返回几个SACK报文?如何返回?


        假设发送方一次发送了60个数据包,编号是从1到60,接收方先接收到了编号为1、2、3及6之后的数据包,4、5、6短时间内还未收到,在不考虑延迟应答的情况下,接收方如何返回ACK报文呢?难道要返回57个<ACK=1 ack=4>的报文吗?来看看TCP是怎么做的。

        st1. 当收到前三个乱序数据包(也就是编号6之后的3个数据包)后,立即返回3个SACK报文,保证丢失的数据包被快速重传;

        st2. 当收到的乱序包数量大于3个(也就是收到编号6之后的数据包已超过3个)后,TCP会对SACK报文进行压缩,最大压缩数量不超过内核参数net.ipv4.tcp_comp_sack_nr设置的值(默认值是44)。压缩SACK报文期间,TCP为减少发送SACK报文次数,并不会立即返回SACK报文,而是延迟发送SACK报文。延迟时间是RTT的5%,也就是RTT/20,但延迟时间最长不超过内核参数 net.ipv4.tcp_comp_sack_delay_ns 设定的值(默认是1ms)。(/* compress ack timer : 5 % of rtt, but no more than tcp_comp_sack_delay_ns */)

        st3. 当SACK报文压缩数量大于等于net.ipv4.tcp_comp_sack_nr参数值后,又是立即发送SACK报文。

5.3 D-SACK

        Duplicate SACK 又称D-SACK,主要是通过SACK来告知发送方有哪些数据被重复接收了。通过D-SACK可让发送方知道是我方发出的报文丢失还是对端返回的ACK报文丢失。如,发送方收到ack= 500,SACK=300-400这样的报文,意味着500之前的数据都接收到了,且重复收到了300-400的数据。D-SACK主要是通知哪些段被重复sack了,也就是发生了一些不必要的重传。

#linux系统中可通过修改net.ipv4.tcp_dsack来决定是否开启SACK,Linux 2.4后默认开启
[root@reader ~]# sysctl -a | grep net.ipv4.tcp_dsack
net.ipv4.tcp_dsack = 1
[root@reader ~]# find / -name *tcp_dsack*
/proc/sys/net/ipv4/tcp_dsack
[root@reader ~]# cat /proc/sys/net/ipv4/tcp_dsack
1
[root@reader ~]# 

可以用echo或sysctl -w 来临时修改tcp_dsack
也可以在系统配置文件 /etc/sysctl.conf 中,添加如下一行代码,永久修改 tcp_dsack
net.ipv4.tcp_dsack= <new_value>

6 流量控制机制

        通过滑动窗口机制有效提高了发送方的数据量和发送速率,但光提高发送方的发送速率也无法彻底解决问题,因为我们未考虑到接收方的数据处理能力,如果发送方的发送速率过高,而接收方的处理速率较低,就会出现接收方无法及时确认应答,发送方触发超时重传的情况,这样的话传输效率还是无法提高。所以,只有在发送方的发送速率与接收方的处理速率同步时,传输效率才能真正提高。

        流量控制机制:发送方根据接收方的实际接收能力来控制自己的发送速率。

        无论是发送方还是接收方,都有一个接收缓冲区,而接收窗口代表了当前可用于接收数据的缓冲区大小,接收方每次进行ACK确认应答时,都会把接收窗口大小放入到报头中的Window字段,发送方收到这条ACK报文后,可根据Window字段获知接收方的接收能力,并通过调整发送窗口大小来调整自己的发送速率,从而适应接收方的接收能力。

        发送方发送窗口的大小由接收方接收窗口的大小决定,但并不意味着两者就完全相等,因为有网络延迟,所以接收窗口大小一般约等于或稍大于发送窗口大小。

6.1 窗口关闭了怎么办?

        当窗口大小Window为0,也就是可用于接收数据的缓冲区大小为0,发送方将停止给接收方发送数据,直到窗口大小变为非 0 为止,这就是窗口关闭

6.2 如何结束窗口关闭状态?

  • 接收方主动结束窗口关闭状态。当接收缓冲区中的部分数据可以被确认时,这部分缓冲空间将被释放,可用于接收新的数据,同时接收方也会给发送方发送ACK报文,并声明Window大小,发送方收到这条ACK报文后会根据Window大小继续发送新的数据。
  • 发送方主动探测窗口关闭状态。只要发送方收到Window=0的ACK报文,就会启动一个定时器,等计时器超时后,发送方会主动发送窗口探测(Window probe)报文,而对方在确认这个探测报文时,会给出自己现在的接收窗口大小。如果接收窗口仍然是0,那就重新启动计时器。如果接收窗口不是0,那就继续发送新的数据。

7 延时应答机制

        延时应答机制建立在滑动窗口机制基础之上,其实就是接收方在接收到报文数据后,并不会立即给发送方返回ACK报文,而是稍等片刻再返回,这样做不仅可以将多次ACK应答合并成一次ACK应答(累计应答),有效减少了ACK应答次数,而且接收方在等待的这段时间内还能处理更多的数据,释放出更多的缓冲空间,接收缓冲区也因此变大,此时再给发送方返回的ACK报文中的Window也会比立即返回报文时的要大。所以,延时应答机制既能减少应答次数,还能变相的增大窗口大小,从而提高传输效率。

8 捎带应答机制

        捎带应答机制建立在延时应答机制基础之上,具体是指当一方要给对方发送非ACK报文时,此时刚好有ACK报文需要返回给对方,那么就将ACK应答内容合并到本报文中捎带着一起发送过去,这样的话可以有效减少应答次数,提高传输效率。

9 拥塞控制机制

        拥塞控制机制针对的是网络层,因为TCP最终还是要将报文段交给了网络层进行传输,如果发送方和接收方都很健康,但在网络层进行数据传输时却因网络拥堵而发生报文丢失、时延较长等问题,这时TCP就会重传报文,重传使得网络更拥堵,报文丢失越严重,重传次数越多,问题就越来越严重,最终会导致连接断开。所以,控制好网络拥塞也是必不可缺的,当发送网络拥塞时,希望TCP可以降低传输效率,提高连接稳定性。于是就有了拥塞控制机制,其主要目的是避免发送方在网络拥塞时发送过多的数据而填满整个网络。

        拥塞控制机制其实是通过不同的策略/算法,不断的探测网络的转发能力,进而调整发送方的发送数据量。为方便调节发送方的发送数据量,便引入了一个叫“拥塞窗口(cwnd)”的概念。

9.1 什么是拥塞窗口(cwnd)

        拥塞窗口(cwnd,congestion window)是发送方维护的一个状态变量,它会根据网络的拥塞程度而动态变化。当网络没有拥塞时,cwnd会不断增大。当网络出现拥塞时,cwnd会不断减小。

        在讲滑动窗口时,曾提到过发送方的发送窗口(swnd)由接收方的接收窗口(rwnd)决定,当引入拥塞窗口之后,发送窗口将由拥塞窗口和接收方的接收窗口共同决定,也就是取拥塞窗口和接收窗口中的最小值。

swnd = min (cwnd, rwnd)

9.2 拥塞控制算法 - 慢启动(Slow-Start)

        TCP在连接建立完成后,由于不清楚网络拥堵情况和对方的处理接收能力,所以在传输数据时有一个慢启动的过程,刚开始先发送较少的数据量,然后再慢慢提高数据发送量。如果刚开始就发送大量数据有可能会直接造成网络瘫痪。

规则发送方每收到一个ACK确认应答,拥塞窗口cwnd就加1。

特点指数性增长。

        TCP有一个状态变量叫慢启动门限/阈值 ssthresh(slow start threshold),一般情况下 ssthresh = 65535

cwndssthresh 时,采用慢启动算法控制拥塞窗口;

当 cwnd >= ssthresh 时,采用拥塞避免算法控制拥塞窗口。

9.3 拥塞控制算法 - 拥塞避免(Congestion Avoidance

        当 cwnd >= ssthresh 时,采用“拥塞避免”算法控制拥塞窗口。

规则发送方每收到一个ACK确认应答,拥塞窗口cwnd就增加1/cwnd

特点线性增长。

9.4 拥塞控制算法 - 拥塞发生

        当发生网络拥塞,即发生数据重传时,或者是当接收方返回EVE报文时,将采用“拥塞发生”算法控制拥塞窗口。但采用的算法规则却不同,因为发生超时重传说明网络拥塞严重,而快速重传和EVE报文相较超时重传的网络拥塞没那么严重,所以超时重传使用较为严格的拥塞控制算法,快速重传和EVE报文使用不太严格的拥塞控制算法。

        超时重传机制对应的拥塞发生算法规则:

  • 先将慢启动门限/阈值 ssthresh 设为 cwnd / 2
  • 再将cwnd重置为初始值(linux系统默认是10,也就是10个MSS);
  • 接着就又重新开始慢启动过程。
# 查看linux系统cwdn初始值
[root@reader ~]# ss -nli | grep cwnd
	 cubic cwnd:10               
	 cubic cwnd:10               
	 cubic cwnd:10               
	 cubic cwnd:10               
	 cubic cwnd:10               
	 cubic cwnd:10               
	 cubic cwnd:10               
	 cubic cwnd:10               
	 cubic cwnd:10               
	 cubic cwnd:10               
	 cubic cwnd:10               
[root@reader ~]# 

 9.5 拥塞控制算法 - 快速恢复(Fast Recovery)

        快速重传(或EVE报文)和快速恢复算法一般同时使用,具体处理过程如下

  • st1.先将cwnd减半,cwnd = cwnd / 2
  • st2.再将慢启动门限/阈值 ssthresh 设为 cwnd
  • st3.拥塞窗口 cwnd ssthresh + 3(已经有3个ACK确认应答了);
  • st4.重传丢失的报文;
  • st5.如果再次收到重复的 ACK 确认应cwnd 就加 1;
  • st6.如果收到新数据的 ACK 确认应,就把 cwnd 设置为 ssthresh 值(也就是 stp2 设置完成的ssthresh值);
  • st7.之后采用拥塞避免算法


参考文章:4.2 TCP 重传、滑动窗口、流量控制、拥塞控制 | 小林coding

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
重庆交通大学信息科学与工程学院 课程设计实验报告 专 业: 学 号: 姓 名: 实验室(中心): 信息技术软件实验室 指 导 教 师 : 实验完成时间: 2015 年 1 月 12 日 目录 实验设计题目---------------------------------------------------------------- -----2 实验目的-------------------------------------------------------------------- -------2 实验设计要求---------------------------------------------------------------- -----2 课程设计条件---------------------------------------------------------------- -----2 五、实验设计分析------------------------------------------------------------ ---------4 六、实验设计流程图---------------------------------------------------------- --------9 七、结果分析---------------------------------------------------------------- -----------13 八、实验心得体会------------------------------------------------------------ ---------14 九、实验主要代码------------------------------------------------------------ ---------15 实验设计题目 基于TCP服务器/客户端程序设计 实验目的 理解客户端与服务器模型的工作原理。 掌握套接字的概念。 掌握TCP协议,基于TCP协议来设计此客户端/服务器程序。 通过设计面向连接的数据流传输服务程序,加深对面向连接的服务程序工作流程和基本 框架的理解。 实验设计要求 1)任选一种编程语言,编程实现面向连接的客户/服务器程序,客户端、服务器端分 别编程; 2) 编程要充分体现服务器端与客户端的连接建立、数据传输、连接释放的过程; 四、课程设计条件 本次课程设计我采用的是JAVA语言,实现客户端和服务器之间的联系。 Java 编程语言的风格十分接近C、C++语言。Java是一个纯的面向对象的程序设计语言,它继 承了 C++语言面向对象技术的核心。Java舍弃了C ++语言中容易引起错误的指针(以引用取代)、运算符重载(operator overloading)、多重继承(以接口取代)等特性,增加了垃圾回收器功能用于回收不再 被引用的对象所占据的内存空间,使得程序员不用再为内存管理而担忧。在 Java 1.5 版本中,Java 又引入了泛型编程(Generic Programming)、类型安全的枚举、不定长参数和自动装/拆箱等语言特性。 Java 不同于一般的编译执行计算机语言和解释执行计算机语言。它首先将源代码编译成二进 制字节码(bytecode),然后依赖各种不同平台上的虚拟机来解释执行字节码。从而实 现了"一次编译、到处执行"的跨平台特性。不过,每次的执行编译后的字节码需要消耗 一定的时间,这同时也在一定程度上降低了 Java 程序的运行效率。 Java语言的变量声明,操作符形式,参数传递,流程控制等方面和C语言,C++语言完 全相同.尽管如此,Java和C语言,C++语言又有许多差别,主要表现在如下几个方面: Java中对内存的分配是动态的,它采用面向对象的机制,采用运算符new为每个对象 分配内存空间,而且,实际内存还会随程序运行情况而改变。程序运行中 Java系统自动对内存进行扫描,对长期不用的空间作为"垃圾"进行收集,使得系统资源 得到更充分地利用.按照这种机制,程序员不必关注内存管理问题,这使Java程序的编写 变得简单明了,并且避免了由于内存管理方面的差错而导致系统出问题。而C语言通过m alloc()和free()这两个库函数来分别实现分配内存和释放内存空间的,C++语言中 则通过运算符new和delete来分配和释放内存。在C和C++这种机制中,程序员必须非常仔 细地处理内存的使用问题。一方面,如果对己释放的内存再作释放或者对未曾分配的内 存作释放,都会造成死机;而另一方面,如果对长期不用的或不再使用的内存不释放, 则会浪费系统资源,甚至因此造成资源枯竭。 Java不在所有类之外定义全局变量

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值