一、流媒体

流媒体是指在internet中使用流媒体技术的连续时基媒体,例如视频、音频或多媒体文件。

流式传输方式是将音视频、动画等多媒体文件经过压缩后分成一个个小数据包,当用户端发出请求时,由服务器端向用户端实时、连续传送这些小数据包,动态变化的网络可能使各个包选择不同的路由,故到达用户端的时间延迟也就不同。在用户端用播放器播放时,需要为接收数据开辟缓存区,以弥补时延和时延抖动的影响和保证数据包传输顺序的正确,经解压缩后,只需要在缓冲区充满前等待几秒钟,就可以连续观看。而同时,后续数据包继续在后台从服务器端以稳定的速率向客户端发送,不影响前台播放。

所以从理论上讲,播放前的延时主要是由于播放器接收、处理前几个数据包引起的,一旦播放就能够保证连续性和稳定性。流式传输的实现不仅需要高效的压缩算法和缓存,而且需要合适的传输协议。

由于tcp需要较多的开销,不太适合传输实时数据。在流式传输的实现方案中,一般采用http/tcp来传输控制信息,而用RTP/UDP来传输实时视音频数据。实现流式传输一般都需要专用的媒体服务器和媒体播放器。

为什么不使用TCP呢?

像TCP这样的可靠传输协议,通过超时和重传机制来保证传输数据流中的每一个bit的正确性,但这样会使得无论从协议的实现还是传输的过程都变得非常的复杂。而且,当传输过程中有数据丢失的时候,由于对数据丢失的检测(超时检测)和重传,会数据流的传输被迫暂停和延时。

RTP协议是一种基于UDP的传输协议,RTP本身并不能为按顺序传送数据包提供可靠的传送机制,也不提供流量控制或拥塞控制,它依靠RTCP提供这些服务。这样,对于那些丢失的数据包,不存在由于超时检测而带来的延时,同时,对于那些丢弃的包,也可以由上层根据其重要性来选择性的重传。比如,对于I帧、P帧、B帧数据,由于其重要性依次降低,故在网络状况不好的情况下,可以考虑在B帧丢失甚至P帧丢失的情况下不进行重传,这样,在客户端方面,虽然可能会有短暂的不清晰画面,但却保证了实时性的体验和要求。

如图所示:

从图中可以看出,RTP被划分在传输层,它建立在UDP上。同UDP协议一样,为了实现其实时传输功能,RTP也有固定的封装形式。RTP用来为端到端的实时传输提供时间信息和流同步,但并不保证服务质量。服务质量由RTCP来提供。

二、流媒体传输的网络协议:RTP与RTCP介绍

1.实时传输协议RTP( Real-time Transport Protocol)

RTP被定义在一对一或一对多传输下工作,其目的是提供时间信息和实现流同步。RTP封装了多媒体应用的数据块。RTP不建立连接,不保证交付,也不进行资源预留。RTP本身并不能为按顺序传送数据包提供可靠的传送机制,也不提供流量控制或拥塞控制,它依靠RTCP提供这些服务。RTP属于应用层协议,在应用发送端,开发者必须编写用RTP封装分组的程序代码。RTP由IETF定义在 RFC 3550和3551中。

2.实时传输控制协议RTCP(RTP Control Ptotocol)

RTCP的主要功能是:服务质量的监视与反馈、媒体间的同步,以及多播组中成员的标识。在RTP会话期间,各参与者周期性地传送RTCP包。RTCP包中含有已发送的数据包的数量、丢失的数据包的数量、数据包到达的平均时间间隔等统计信息,因此,各参与者可以利用这些信息动态地改变传输速率,甚至改变有效载荷类型。RTP和RTCP配合使用,它们能以有效的反馈和最小的开销使传输效率最佳化,因而特别适合传送网上的实时数据。

三、RTP与RTCP的协议层次及封装

RTP位于传输层(通常是UDP)之上,应用程序之下,实时语音、视频数据经过模数转换和压缩编码处理后,先送给RTP封装成为RTP数据单元,RTP数据单元被封装为UDP数据报,然后再向下递交给IP封装为IP数据包。
RTP分组只包含RTP数据,而控制是由另一个配套协议RTCP提供。RTP在端口号1024到65535之间选择一个未使用的偶数UDP端口号,而在同一次会话中的RTCP则使用下一个奇数UDP端口号。
  
具体会话流程为

1)RTP协议从上层接收流媒体信息码流(如H.263),封装成RTP数据包;RTCP从上层接收控制信息,封装成RTCP控制包。
2)RTP将RTP数据包发往UDP端口对中偶数端口;RTCP将RTCP控制包发往UDP端口对中的接收端口。

RTP通常和RTCP一起工作,在RTP会话期间,各参与者周期的发送RTCP消息。RTCP消息也被封装为UDP数据报进行传输。
RTP数据协议负责对流媒体数据进行封包并实现媒体流的实时传输,每一个RTP数据报都由头部(Header)和负载(Payload)两个部分组成,其中头部的含义是固定的,而负载则可以是音频或者视频数据。

四、RTP协议头信息

0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±+
|V=2|P|X| CC |M| PT | sequence number |
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±+
| timestamp |
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±+
| synchronization source (SSRC) identifier |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
| contributing source (CSRC) identifiers |
| … |
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±+

version (V): 2 bits
  
标明RTP版本号。协议初始版本为0,RFC3550中规定的版本号为2。

padding §: 1 bit

如果该位被设置,则在该packet末尾包含了额外的附加信息,附加信息的最后一个字节表示额外附加信息的长度(包含该字节本身)。该字段之所以存在是因为一些加密机制需要固定长度的数据块,或者为了在一个底层协议数据单元中传输多个RTP packets。

extension (X): 1 bit

如果该位被设置,则在固定的头部后存在一个扩展头部,格式定义在RFC3550 5.3.1节。

CSRC count (CC): 4 bits

在固定头部后存在多少个CSRC标记。

marker (M): 1 bit

该位的功能依赖于profile的定义。profile可以改变该位的长度,但是要保持marker和payload type总长度不变(一共是8 bit)。

payload type (PT): 7 bits

标记着RTP packet所携带信息的类型,标准类型列出在RFC3551中。如果接收方不能识别该类型,必须忽略该packet。负载类型主要用来告诉接收端(或者播放器)传输的是哪种类型的媒体(例如G.729,H.264,MPEG-4等),这样接收端(或者播放器)才知道了数据流的格式,才会调用适当的编解码器去解码或者播放,这就是负载类型的主要作用。

sequence number: 16 bits

序列号,每个RTP packet发送后该序列号加1,接收方可以根据该序列号重新组合数据包顺序,判断包是否丢失等操作。注意:它只是表示了包的先后顺序,它不能表示时间上的任何其它信息。

timestamp: 32 bits

时间戳。反映RTP packet所携带信息包中第一个字节的采样时间(详见下文)。

SSRC: 32 bits

同步数据源Synchronization source标识。在一个RTP Session其间每个数据流都应该有一个不同的SSRC。

CSRC list: 0 to 15 items, 每个源标识32 bits

贡献数据源Contributing source标识。只有存在Mixer的时候才有效。如一个将多声道的语音流合并成一个单声道的语音流,在这里就列出原来每个声道的SSRC。

重要组成

CSRC记数(CC):表示CSRC标识的数目。CSRC标识紧跟在RTP固定头部之后,用来表示RTP数据报的来源,RTP协议允许在同一个会话中存在多个数据源,它们可以通过RTP混合器合并为一个数据源。例如,可以产生一个CSRC列表来表示一个电话会议,该会议通过一个RTP混合器将所有讲话者的语音数据组合为一个RTP数据源。

负载类型(PT):标明RTP负载的格式,包括所采用的编码算法、采样频率、承载通道等。例如,类型2表明该RTP数据包中承载的是用ITU G.721算法编码的语音数据,采样频率为8000Hz,并且采用单声道。

序列号:用来为接收方提供探测数据丢失的方法,但如何处理丢失的数据则是应用程序自己的事情,RTP协议本身并不负责数据的重传。

时间戳:记录了负载中第一个字节的采样时间,接收方能够时间戳能够确定数据的到达是否受到了延迟抖动的影响,但具体如何来补偿延迟抖动则是应用程序自己的事情。

从RTP数据报的格式不难看出,它包含了传输媒体的类型、格式、序列号、时间戳以及是否有附加数据等信息,这些都为实时的流媒体传输提供了相应的基础。RTP协议的目的是提供实时数据(如交互式的音频和视频)的端到端传输服务,因此在RTP中没有连接的概念,它可以建立在底层的面向连接或面向非连接的传输协议之上;RTP也不依赖于特别的网络地址格式,而仅仅只需要底层传输协议支持组帧(Framing)和分段(Segmentation)就足够了;另外RTP本身还不提供任何可靠性机制,这些都要由传输协议或者应用程序自己来保证。在典型的应用场合下,RTP一般是在传输协议之上作为应用程序的一部分加以实现的。

关于RTP的时间戳(timestamp):

时间戳单位:时间戳计算的单位不是秒,而是采用采样频率的倒数,这样做的目的是为了使时间戳单位更为精准。比如说一个音频的采样频率为8000Hz,那么我们可以把时间戳单位设为1/8000s。

时间戳增量:相邻两个RTP包之间的时间差(以时间戳单位为基准)

采样频率: 每秒钟抽取样本的次数,例如音频的采样率一般为8000Hz,即每秒采样8000次,产生8000个样本

帧率: 每秒传输或者显示帧数,例如25f/s

时间戳反映了RTP分组中的数据的第一个字节的采样时刻。在一次会话开始时的时间戳初值也是随机选择的。即使是没有信号发送时,时间戳的数值也要随时间不断的增加。接收端使用时间戳可准确知道应当在什么时间还原哪一个数据块,从而消除传输中的抖动。时间戳还可用来使视频应用中声音和图像同步。

在RTP协议中并没有规定时间戳的粒度,这取决于有效载荷的类型。因此RTP的时间戳又称为媒体时间戳,以强调这种时间戳的粒度取决于信号的类型。例如,对于8kHz采样的音频信号,若每隔20ms构成一个数据块,则一个数据块中包含有160个样本(0.02×8000=160)。因此每发送一个RTP分组,其时间戳的值就增加160。

如果采样频率为90000Hz,则时间戳单位为1/90000,我们就假设1s钟被划分了90000个时间块,那么,如果每秒发送25帧,那么,每一个帧的发送占多少个时间块呢?当然是 90000/25 = 3600。因此,我们根据定义“时间戳增量是发送第二个RTP包相距发送第一个RTP包时的时间间隔”,故时间戳增量应该为3600。

时间戳可用来使视频应用中声音和图像同步,为什么呢?
首先,时间戳就是一个值,用来反映某个数据块的产生(采集)时间点的, 后采集的数据块的时间戳肯定是大于先采集的数据块的。有了这样一个时间戳,就可以标记数据块的先后顺序。
第二,在实时流传输中,数据采集后立刻传递到RTP 模块进行发送,那么,其实,数据块的采集时间戳就直接作为RTP包的时间戳。
第三,如果用RTP来传输固定的文件,则这个时间戳 就是读文件的时间点,依次递增。这个不再我们当前的讨论范围内,暂时不考虑。

五、RTCP协议

RTCP协议处理机定义了五种类型的报文,它们完成接收、分析、产生和发送控制报文的功能。

1. SR(sender report)发送者报告分组:用来使发送端周期的向所有接收端用多播方式进行报告。内容包括:

该RTP流的SSRC(Synchronization source);该RTP流中最新产生的RTP分组的时间戳和绝对时钟时间(或称墙上时间:wall clock time);该RTP流包含的分组数;该RTP流包含的字节数。

绝对时钟时间是必要的。因为RTP要求每一种媒体使用一个流。有了绝对时钟时间就可以进行图形和声音的同步。

2. RR(receiver report)接收者报告分组:用来使接收端周期性的向所有的点用多播方式进行报告。内容包括所接收到的RTP流的SSRC;该RTP流的分组丢失率;在该RTP流中的最后一个RTP分组的序号;分组到达时间间隔的抖动等。

发送RR分组有两个目的。第一,可以使所有的接收端和发送端了解当前网络的状态。

第二,可以使所有发送RTCP分组的站点自适应的调整自己发送RTCP分组的速率,RTCP分组的通信量不超过网络中的数据分组的通信量的5%,而接收端分组报告分组的通信量又应小于所有RTCP分组的通信量的75%。

3.SDES(source description items)源描述分组:给出会话中参加者的描述,包括参加者的规范名(CNAME)。(源描述,主要功能是作为会话成员有关标识信息的载体,如用户名、邮件地址、电话号码等,此外还具有向会话成员传达会话控制信息的功能。)

4.BYE(indicates end of participation)分组:通知离开,主要功能是指示某一个或者几个源不再有效,即通知会话中的其他成员自己将退出会话。

5.APP(application specific functions)分组:应用程序能够定义新的分组类型。(由应用程序自己定义,解决了RTCP的扩展性问题,并且为协议的实现者提供了很大的灵活性。)

在RTCP中,还有两个比较重要的东西,一个64位的绝对时间戳和一个32位的相对时间戳。64 位时间戳也叫NTP时间戳,它的前 32位是从1900 年1 月1 日0 时开始到现在的以秒为单位的整数部分,后32位是此时间的小数部,因此,它可以肯定的表示了数据发送出去的绝对时间。32位的时间戳和RTP中的时间戳是一样的,没有任何区别。

RTCP数据报携带有服务质量监控的必要信息,能够对服务质量进行动态的调整,并能够对网络拥塞进行有效的控制。由于RTCP数据报采用的是多播方式,因此会话中的所有成员都可以通过RTCP数据报返回的控制信息,来了解其他参与者的当前情况。

在一个典型的应用场合下,发送媒体流的应用程序将周期性地产生发送端报告SR,该RTCP数据报含有不同媒体流间的同步信息,以及已经发送的数据报和字节的计数,接收端根据这些信息可以估计出实际的数据传输速率。

另一方面,接收端会向所有已知的发送端发送接收端报告RR,该RTCP数据报含有已接收数据报的最大序列号、丢失的数据报数目、延时抖动和时间戳等重要信息,发送端应用根据这些信息可以估计出往返时延,并且可以根据数据报丢失概率和时延抖动情况动态调整发送速率,以改善网络拥塞状况,或者根据网络状况平滑地调整应用程序的服务质量。

六、媒体流的同步:流内同步和流间同步

多媒体通信同步方法,主要有时间戳同步法、同步标记法、多路复用同步法三种。下面主要讨论时间戳同步法,特别是RTP时间戳同步。内容包括RTP媒体间同步的实现,为什么需要RTCP的NTP时间来实现媒体间同步?没有RTCP,能实现RTP媒体间的同步吗?

序列号字段是否可以作为流内的同步标识?序列号只表示了包发出的先后顺序,它表示不了任何时间上的其它概念,所以严格的说,序列号并不能作为流内的同步标志。但是,由于一般来说,包的发送时间都会有严格限制,比如音频包是每秒种发送30个数据包,也就是说,每个包间隔1000/30MS,而这个时间就可以 作为一个同步时间来播放。也就是说,按照序列号,每1000/30MS间隔播放一个数据包,这样也能保证同步,但是这时候请考虑丢包问题。

根据RTP规范,不同的RTP媒体流是分开传输的,且使用各自独立的时间戳进行同步。假设在一次视频点播中,传输两路RTP媒体流,一路视频,一路音频。根据视频帧时间戳,可以实现视频流内同步,这很好理解,通过视频帧时间戳可以计算出相邻视频帧的时间间隔,也就是视频帧之间的相对时间关系很容易通过时间戳来确定,按照这个间隔去呈现视频,就可以获得较好的效果。同理,音频流也可以实现自身的同步。那么音频和视频这两路媒体间如何实现同步呢?我们只使用音视频的RTP时间戳,看能否实现媒体间的同步。音视频的RTP时间戳的增长速率一般是不同的,但没关系,知道了具体的单位后,两者是可以通过单位换算联系起来的。如下:

视频帧时间戳单位:90000Hz,帧率:25fps
音频帧时间戳单位:8000Hz,帧率:50fps
A:音频帧 V:视频帧 A/V:音频帧和视频帧
音频帧时间戳:0 160 320 480 640 … 音频时间轴
视频帧时间戳:0 3600 7200 … 视频时间轴

        A/V   A     A/V     A     A/V

绝对时间轴: 0 20 40 60 80 … 单位:ms
  现在来看,这种方法好像可以实现同步,因为音视频被映射到同一个时间轴上了,音频和视频帧间的相对关系很清楚。慢着,RTP规范要求时间戳的初 始值应该是一个随机值,那么假设音频帧时间戳的初始值是随机值1234,视频帧时间戳的初始值是随机值5678,看起来应该是下面这样:

音频帧时间戳:1234 1394 1554 1714 1874 … 音频时间轴
视频帧时间戳:5678 9278 12878 … 视频时间轴

    A/V   A     A/V      A      A/V

绝对时间轴: 0 20 40 60 80 … 单位:ms
  这么做合适吗?我们把音频帧时间戳1234和视频帧时间戳5678对应到绝对时间轴的0上,我们这么做的理由是什么?你可能会说,因为那是第一个音频帧和第一个视频帧,所以可以对应到同一个点上,在第一幅图中我们就是这么做的,把音频帧时间戳0和视频帧时间戳0对应到绝对时间轴的0上。但是RTP规范并没有规定第一个视频帧的时间戳和第一个音频帧的时间戳必须或者应该对应到绝对时间轴的同一个点上,从整个RTP规范中不能直接得出这样的结论,也推导不出这样的结论。

我们上面两幅图所做的转换是不正确的,为什么呢?因为在做转换时,隐含了一个假设,我们想当然地认为这个假设是成立的,实际上它并不总是成立。这个假设就是第一个视频帧和第一个音频帧的时间戳应该对应到同一个点上,即无论它们时间戳是多少,都应该在同一时间播放。

仅仅使用RTP时间戳是无法实现媒体间同步的,根本的原因是音频时间轴和视频时间轴是完全独立的,通过音频帧和视频帧的时间戳,无法确定一个视频帧和一个音频帧的相对时间关系,也就是无法把它们都准确定位在绝对时间轴上。

要实现RTP媒体间同步,需要借助于RTCP,在RTCP的SR包中,包含有对,音频帧RTP时间戳和视频帧RTP时间戳通过对,都可以准确定位到绝对时间轴NTP上,音频帧和视频帧的相对时间关系就可以确定下来 了。

上面提到,我们的那个隐含的假设并不总是成立,那就是说它有成立的时候。那是不是说当它成立时,我们就可以不用RTCP来做媒体间同步了?答案是,基本上可以这么认为。例如,对于RTP实时流,在发送端媒体间就同步的很好,在接收端只需做少许处理,不需要RTCP,就可以实现媒体间同步。当然,这只是少数例外。因为RTP规范并不包括这个假设,所以我们还是按照RTP规范来做吧。

七、RTSP

RTSP的请求主要有DESCRIBE、SETUP、PLAY、PAUSE、TEARDOWN、OPTIONS等,顾名思义可以知道起对话和控制作用,RTSP的对话过程中SETUP可以确定RTP/RTCP使用的端口,PLAY/PAUSE/TEARDOWN可以开始或者停止RTP的发送,等等。

作为一个应用层协议,RTSP提供了一个可供扩展的框架,它的意义在于使得实时流媒体数据的受控和点播变得可能。总的说来,RTSP是一个流媒体表示协议,主要用来控制具有实时特性的数据发送,但它本身并不传输数据,而是必须依赖于下层传输协议(RTP)所提供的某些服务。

RTSP可以对流媒体提供诸如播放、暂停、快进等操作,它负责定义具体的控制消息、操作方法、状态码等,此外还描述了与RTP间的交互操作(RFC2326)。

RTSP在制定时较多地参考了HTTP/1.1协议,甚至许多描述与HTTP/1.1完全相同。RTSP之所以特意使用与HTTP/1.1类似的语法和操作,在很大程度上是为了兼容现有的Web基础结构,正因如此,HTTP/1.1的扩展机制大都可以直接引入到RTSP中。

由RTSP控制的媒体流集合可以用表示描述(Presentation Description)来定义,所谓表示是指流媒体服务器提供给客户机的一个或者多个媒体流的集合,而表示描述则包含了一个表示中各个媒体流的相关信息,如数据编码/解码算法、网络地址、媒体流的内容等。

虽然RTSP服务器同样也使用标识符来区别每一流连接会话(Session),但RTSP连接并没有被绑定到传输层连接(如TCP等),也就是说在整个RTSP连接期间,RTSP用户可打开或者关闭多个对RTSP服务器的可靠传输连接以发出RTSP 请求。此外,RTSP连接也可以基于面向无连接的传输协议(如UDP等)。

RTP提供时间标志,序列号以及其他能够保证在实时数据传输时处理时间的方法
RTCP是RTP的控制部分,是用来保证服务质量和成员管理的
RTSP具体数据传输交给RTP,提供对流的远程控制
RSVP预留带宽,提高QoS(Quality of Sever)

RTSP与RTP最大的区别在于:RTSP是一种双向实时数据传输协议,它允许客户端向服务器端发送请求,如回放、快进、倒退等操作。
RTSP可基于RTP来传送数据,还可以选择TCP、UDP、组播UDP等通道来发送数据,具有很好的扩展性。
RTSP 默认使用554端口, 非常类似 HTTP 协议的流控制协议, rtsp 的命令总是按照顺序来发送.

参考1
参考2

[RTC] RTP/RTCPRTSP及音视频同步相关知识相关推荐

  1. Android 音视频开发相关知识

    音视频开发技能 要在Android上进行音视频开发,需要掌握以下技能: Android开发:首先,您需要掌握Android应用程序的基本开发技能,包括Java或Kotlin编程语言,Android S ...

  2. FFmpeg音视频同步基础知识

    1. I帧/P帧/B帧 I帧:I帧(Intra-coded picture, 帧内编码帧,常称为关键帧)包含一幅完整的图像信息,属于帧内编码图像,不含运动矢量,在解码时不需要参考其他帧图像.因此在I帧 ...

  3. WebRTC 音视频同步分析

    文中提到的代码引用自 libwebrtc M96 版本 https://github.com/aggresss/libwebrtc/tree/M96 0x00 前言 WebRTC 音频和视频分别通过不 ...

  4. vlc源码分析(五) 流媒体的音视频同步

    vlc播放流媒体时实现音视频同步,简单来说就是发送方发送的RTP包带有时间戳,接收方根据此时间戳不断校正本地时钟,播放音视频时根据本地时钟进行同步播放.首先了解两个概念:stream clock和sy ...

  5. 音视频同步(播放)原理

    每一帧音频或视频都有一个持续时间:duration: 采样频率是指将模拟声音波形进行数字化时,每秒钟抽取声波幅度样本的次数. .正常人听觉的频率范围大约在20Hz~20kHz之间,根据奈奎斯特采样理论 ...

  6. FFmpeg 音视频同步

    原地址:http://www.jianshu.com/p/27279255f67e 音视频播放器的工作的具体流程如下图所示: 播放器工作流程 简单的来说包括:解协议,解封装,对音频和视频分别进行解码, ...

  7. ffmpeg rtsp转hls_Qt音视频开发24-ffmpeg音视频同步

    ## 一.前言 用ffmpeg来做音视频同步,个人认为这个是ffmpeg基础处理中最难的一个,无数人就卡在这里,怎么也不准,本人也是尝试过网上各种demo,基本上都是渣渣,要么仅仅支持极其少量的视频文 ...

  8. ffmpeg源码分析_ffmpeg音视频同步的几种策略

    在前面的文章中,我们介绍了播放器的视频渲染及音频渲染的相关知识,这些都是单独进行的,一旦在现实开发中将视频及音频结合在一起播放就会出现音视频不同步的问题. 下面我们就来分析一下如何解决音视频同步的问题 ...

  9. NDK开发——FFmpeg实现视频转YUV、视频转RGB显示、音频转PCM、音频播放、音视频同步

    项目演示 前提准备 编译FFmpeg+CMake并能运行,详细可见我博客 下载libyuv库并编译成libyuv.so库,用于实现转换RGB格式功能 FFmpeg库简介 avcodec:编解码,包含 ...

最新文章

  1. 深入探索 Java 热部署--转
  2. 反斜杠转义mysql java_mysql数据库中的反斜杠”\“怎么使用Java进行转义
  3. Pandas知识点-比较操作
  4. 并发高?可能是编译优化引发有序性问题
  5. 微软宣布免费 Web 版 Office 2010发布日期
  6. C#设计模式(13)——代理模式(Proxy Pattern)
  7. 微软公布测试版Visual Studio for Mac和Visual Studio 2017 for Windows
  8. iOS 刘海屏 隐藏横条 home键
  9. Java 8 异步 API、循环、日期,用好提高生产力!
  10. HAOI2018 反色游戏
  11. 并发(二)——linux内核同步机制分析
  12. redis:集群配置
  13. 2022年华数杯数学建模
  14. vue创建项目自定义配置
  15. npm ERR code ETIMEDOUT npm ERR syscall connect npm ERR errno ETIMEDOUT npm ERR network reques...
  16. 悉尼大学高级计算机专业世界排名,悉尼大学专业排名一览及最强专业推荐(QS世界大学排名)...
  17. 最小公倍数求解完全解读
  18. FIR Filter
  19. args在python中什么意思_Python中*args、**args到底是什么、有啥区别、怎么用
  20. 升余弦和根升余弦滤波器(SRRC,RRC)的单位脉冲响应

热门文章

  1. React学习day13--antd组件:Layout布局
  2. Vue使用filters过滤时不能使用this的解决办法——两次遇到了,一定要记住奥~
  3. await实现并发的原理
  4. 基于ofbiz的适合中国工厂的大型制造业erp产品
  5. 图片上传实现(搭建Nginx图片服务器[第五课])
  6. 网站内容页面怎样优化?深度解析内容页面优化技巧
  7. 《Python零基础快乐学习之旅》学习笔记3——Python的基本数据类型
  8. java实现线程通信的几种方式
  9. Python之Numpy详细教程
  10. 地球的自转轴线和水平线的角度