使用C#实现RTP数据包传输 参照RFC3550

闲暇时折腾IP网络视频监控系统,需要支持视频帧数据包在网络内的传输。
未采用H.264或MPEG4等编码压缩方式,直接使用Bitmap图片。
由于对帧的准确到达要求不好,所以采用UDP传输。如果发生网络丢包现象则直接将帧丢弃。
为了记录数据包的传输顺序和帧的时间戳,所以研究了下RFC3550协议,采用RTP包封装视频帧。
并未全面深究,所以未使用SSRC和CSRC,因为不确切了解其用意。不过目前的实现情况已经足够了。


代码如下:

/// <summary>
   /// RTP(RFC3550)协议数据包
   /// </summary>
   /// <remarks>
   /// The RTP header has the following format:
   ///  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                        |
   /// | ....                                                          |
   /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   /// </remarks>
   public class RtpPacket
   {
     /// <summary>
     /// version (V): 2 bits
     /// RTP版本标识,当前规范定义值为2.
     /// This field identifies the version of RTP. The version defined by this specification is two (2).
     /// (The value 1 is used by the first draft version of RTP and the value 0 is used by the protocol
     /// initially implemented in the \vat" audio tool.)
     /// </summary>
     public int Version { get { return 2; } }

/// <summary>
     /// padding (P):1 bit
     /// 如果设定padding,在报文的末端就会包含一个或者多个padding 字节,这不属于payload。
     /// 最后一个字节的padding 有一个计数器,标识需要忽略多少个padding 字节(包括自己)。
     /// 一些加密算法可能需要固定块长度的padding,或者是为了在更低层数据单元中携带一些RTP 报文。
     /// If the padding bit is set, the packet contains one or more additional padding octets at the
     /// end which are not part of the payload. The last octet of the padding contains a count of
     /// how many padding octets should be ignored, including itself. Padding may be needed by
     /// some encryption algorithms with fixed block sizes or for carrying several RTP packets in a
     /// lower-layer protocol data unit.
     /// </summary>
     public int Padding { get { return 0; } }

/// <summary>
     /// extension (X):1 bit
     /// 如果设定了extension 位,定长头字段后面会有一个头扩展。
     /// If the extension bit is set, the fixed header must be followed by exactly one header extensio.
     /// </summary>
     public int Extension { get { return 0; } }

/// <summary>
     /// CSRC count (CC):4 bits
     /// CSRC count 标识了定长头字段中包含的CSRC identifier 的数量。
     /// The CSRC count contains the number of CSRC identifiers that follow the fixed header.
     /// </summary>
     public int CC { get { return 0; } }

/// <summary>
     /// marker (M):1 bit
     /// marker 是由一个profile 定义的。用来允许标识在像报文流中界定帧界等的事件。
     /// 一个profile 可能定义了附加的标识位或者通过修改payload type 域中的位数量来指定没有标识位.
     /// The interpretation of the marker is defined by a profile. It is intended to allow significant
     /// events such as frame boundaries to be marked in the packet stream. A profile may define
     /// additional marker bits or specify that there is no marker bit by changing the number of bits
     /// in the payload type field.
     /// </summary>
     public int Marker { get { return 0; } }

/// <summary>
     /// payload type (PT):7 bits
     /// 这个字段定一个RTPpayload 的格式和在应用中定义解释。
     /// profile 可能指定一个从payload type 码字到payload format 的默认静态映射。
     /// 也可以通过non-RTP 方法来定义附加的payload type 码字(见第3 章)。
     /// 在 RFC 3551[1]中定义了一系列的默认音视频映射。
     /// 一个RTP 源有可能在会话中改变payload type,但是这个域在复用独立的媒体时是不同的。(见5.2 节)。
     /// 接收者必须忽略它不识别的payload type。
     /// This field identifies the format of the RTP payload and determines its interpretation by the
     /// application. A profile may specify a default static mapping of payload type codes to payload
     /// formats. Additional payload type codes may be defined dynamically through non-RTP means
     /// (see Section 3). A set of default mappings for audio and video is specified in the companion
     /// RFC 3551 [1]. An RTP source may change the payload type during a session, but this field
     /// should not be used for multiplexing separate media streams (see Section 5.2).
     /// A receiver must ignore packets with payload types that it does not understand.
     /// </summary>
     public RtpPayloadType PayloadType { get; private set; }

/// <summary>
     /// sequence number:16 bits
     /// 每发送一个RTP 数据报文序列号值加一,接收者也可用来检测丢失的包或者重建报文序列。
     /// 初始的值是随机的,这样就使得known-plaintext 攻击更加困难, 即使源并没有加密(见9。1),
     /// 因为要通过的translator 会做这些事情。关于选择随机数方面的技术见[17]。
     /// The sequence number increments by one for each RTP data packet sent, and may be used
     /// by the receiver to detect packet loss and to restore packet sequence. The initial value of the
     /// sequence number should be random (unpredictable) to make known-plaintext attacks on
     /// encryption more dificult, even if the source itself does not encrypt according to the method
     /// in Section 9.1, because the packets may flow through a translator that does. Techniques for
     /// choosing unpredictable numbers are discussed in [17].
     /// </summary>
     public int SequenceNumber { get; private set; }

/// <summary>
     /// timestamp:32 bits
     /// timestamp 反映的是RTP 数据报文中的第一个字段的采样时刻的时间瞬时值。
     /// 采样时间值必须是从恒定的和线性的时间中得到以便于同步和jitter 计算(见第6.4.1 节)。
     /// 必须保证同步和测量保温jitter 到来所需要的时间精度(一帧一个tick 一般情况下是不够的)。
     /// 时钟频率是与payload 所携带的数据格式有关的,在profile 中静态的定义或是在定义格式的payload format 中,
     /// 或通过non-RTP 方法所定义的payload format 中动态的定义。如果RTP 报文周期的生成,就采用虚拟的(nominal)
     /// 采样时钟而不是从系统时钟读数。例如,在固定比特率的音频中,timestamp 时钟会在每个采样周期时加一。
     /// 如果音频应用中从输入设备中读入160 个采样周期的块,the timestamp 就会每一块增加160,
     /// 而不管块是否传输了或是丢弃了。
     /// 对于序列号来说,timestamp 初始值是随机的。只要它们是同时(逻辑上)同时生成的,
     /// 这些连续的的 RTP 报文就会有相同的timestamp,
     /// 例如,同属一个视频帧。正像在MPEG 中内插视频帧一样,
     /// 连续的但不是按顺序发送的RTP 报文可能含有相同的timestamp。
     /// The timestamp reflects the sampling instant of the first octet in the RTP data packet. The
     /// sampling instant must be derived from a clock that increments monotonically and linearly
     /// in time to allow synchronization and jitter calculations (see Section 6.4.1). The resolution
     /// of the clock must be suficient for the desired synchronization accuracy and for measuring
     /// packet arrival jitter (one tick per video frame is typically not suficient). The clock frequency
     /// is dependent on the format of data carried as payload and is specified statically in the profile
     /// or payload format specification that defines the format, or may be specified dynamically for
     /// payload formats defined through non-RTP means. If RTP packets are generated periodically,
     /// the nominal sampling instant as determined from the sampling clock is to be used, not a
     /// reading of the system clock. As an example, for fixed-rate audio the timestamp clock would
     /// likely increment by one for each sampling period. If an audio application reads blocks covering
     /// 160 sampling periods from the input device, the timestamp would be increased by 160 for
     /// each such block, regardless of whether the block is transmitted in a packet or dropped as silent.
     /// </summary>
     public long Timestamp { get; private set; }

/// <summary>
     /// SSRC:32 bits
     /// SSRC 域识别同步源。为了防止在一个会话中有相同的同步源有相同的SSRC identifier,
     /// 这个identifier 必须随机选取。
     /// 生成随机 identifier 的算法见目录A.6 。虽然选择相同的identifier 概率很小,
     /// 但是所有的RTP implementation 必须检测和解决冲突。
     /// 第8 章描述了冲突的概率和解决机制和RTP 级的检测机制,根据唯一的 SSRCidentifier 前向循环。
     /// 如果有源改变了它的源传输地址,
     /// 就必须为它选择一个新的SSRCidentifier 来避免被识别为循环过的源(见第8.2 节)。
     /// The SSRC field identifies the synchronization source. This identifier should be chosen
     /// randomly, with the intent that no two synchronization sources within the same RTP session
     /// will have the same SSRC identifier. An example algorithm for generating a random identifier
     /// is presented in Appendix A.6. Although the probability of multiple sources choosing the same
     /// identifier is low, all RTP implementations must be prepared to detect and resolve collisions.
     /// Section 8 describes the probability of collision along with a mechanism for resolving collisions
     /// and detecting RTP-level forwarding loops based on the uniqueness of the SSRC identifier. If
     /// a source changes its source transport address, it must also choose a new SSRC identifier to
     /// avoid being interpreted as a looped source (see Section 8.2).
     /// </summary>
     public int SSRC { get { return 0; } }

/// <summary>
     /// 每一个RTP包中都有前12个字节定长的头字段
     /// The first twelve octets are present in every RTP packet
     /// </summary>
     public const int HeaderSize = 12;
     /// <summary>
     /// RTP消息头
     /// </summary>
     private byte[] _header;
     /// <summary>
     /// RTP消息头
     /// </summary>
     public byte[] Header { get { return _header; } }

/// <summary>
     /// RTP有效载荷长度
     /// </summary>
     private int _payloadSize;
     /// <summary>
     /// RTP有效载荷长度
     /// </summary>
     public int PayloadSize { get { return _payloadSize; } }

/// <summary>
     /// RTP有效载荷
     /// </summary>
     private byte[] _payload;
     /// <summary>
     /// RTP有效载荷
     /// </summary>
     public byte[] Payload { get { return _payload; } }

/// <summary>
     /// RTP消息总长度,包括Header和Payload
     /// </summary>
     public int Length { get { return HeaderSize + PayloadSize; } }

/// <summary>
     /// RTP(RFC3550)协议数据包
     /// </summary>
     /// <param name="playloadType">数据报文有效载荷类型</param>
     /// <param name="sequenceNumber">数据报文序列号值</param>
     /// <param name="timestamp">数据报文采样时刻</param>
     /// <param name="data">数据</param>
     /// <param name="dataSize">数据长度</param>
     public RtpPacket(
       RtpPayloadType playloadType,
       int sequenceNumber,
       long timestamp,
       byte[] data,
       int dataSize)
     {
       // fill changing header fields
       SequenceNumber = sequenceNumber;
       Timestamp = timestamp;
       PayloadType = playloadType;

// build the header bistream
       _header = new byte[HeaderSize];

// fill the header array of byte with RTP header fields
       _header[0] = (byte)((Version << 6) | (Padding << 5) | (Extension << 4) | CC);
       _header[1] = (byte)((Marker << 7) | (int)PayloadType);
       _header[2] = (byte)(SequenceNumber >> 8);
       _header[3] = (byte)(SequenceNumber);
       for (int i = 0; i < 4; i++)
       {
         _header[7 - i] = (byte)(Timestamp >> (8 * i));
       }
       for (int i = 0; i < 4; i++)
       {
         _header[11 - i] = (byte)(SSRC >> (8 * i));
       }

// fill the payload bitstream
       _payload = new byte[dataSize];
       _payloadSize = dataSize;

// fill payload array of byte from data (given in parameter of the constructor)
       Array.Copy(data, 0, _payload, 0, dataSize);
     }

/// <summary>
     /// RTP(RFC3550)协议数据包
     /// </summary>
     /// <param name="playloadType">数据报文有效载荷类型</param>
     /// <param name="sequenceNumber">数据报文序列号值</param>
     /// <param name="timestamp">数据报文采样时刻</param>
     /// <param name="frame">图片</param>
     public RtpPacket(
       RtpPayloadType playloadType,
       int sequenceNumber,
       long timestamp,
       Image frame)
     {
       // fill changing header fields
       SequenceNumber = sequenceNumber;
       Timestamp = timestamp;
       PayloadType = playloadType;

// build the header bistream
       _header = new byte[HeaderSize];

// fill the header array of byte with RTP header fields
       _header[0] = (byte)((Version << 6) | (Padding << 5) | (Extension << 4) | CC);
       _header[1] = (byte)((Marker << 7) | (int)PayloadType);
       _header[2] = (byte)(SequenceNumber >> 8);
       _header[3] = (byte)(SequenceNumber);
       for (int i = 0; i < 4; i++)
       {
         _header[7 - i] = (byte)(Timestamp >> (8 * i));
       }
       for (int i = 0; i < 4; i++)
       {
         _header[11 - i] = (byte)(SSRC >> (8 * i));
       }

// fill the payload bitstream
       using (MemoryStream ms = new MemoryStream())
       {
         frame.Save(ms, ImageFormat.Jpeg);
         _payload = ms.ToArray();
         _payloadSize = _payload.Length;
       }
     }

/// <summary>
     /// RTP(RFC3550)协议数据包
     /// </summary>
     /// <param name="packet">数据包</param>
     /// <param name="packetSize">数据包长度</param>
     public RtpPacket(byte[] packet, int packetSize)
     {
       //check if total packet size is lower than the header size
       if (packetSize >= HeaderSize)
       {
         //get the header bitsream
         _header = new byte[HeaderSize];
         for (int i = 0; i < HeaderSize; i++)
         {
           _header[i] = packet[i];
         }

//get the payload bitstream
         _payloadSize = packetSize - HeaderSize;
         _payload = new byte[_payloadSize];
         for (int i = HeaderSize; i < packetSize; i++)
         {
           _payload[i - HeaderSize] = packet[i];
         }

//interpret the changing fields of the header
         PayloadType = (RtpPayloadType)(_header[1] & 127);
         SequenceNumber = UnsignedInt(_header[3]) + 256 * UnsignedInt(_header[2]);
         Timestamp = UnsignedInt(_header[7])
           + 256 * UnsignedInt(_header[6])
           + 65536 * UnsignedInt(_header[5])
           + 16777216 * UnsignedInt(_header[4]);
       }
     }

/// <summary>
     /// 将消息转换成byte数组
     /// </summary>
     /// <returns>消息byte数组</returns>
     public byte[] ToArray()
     {
       byte[] packet = new byte[Length];

Array.Copy(_header, 0, packet, 0, HeaderSize);
       Array.Copy(_payload, 0, packet, HeaderSize, PayloadSize);

return packet;
     }

/// <summary>
     /// 将消息体转换成图片
     /// </summary>
     /// <returns>图片</returns>
     public Bitmap ToBitmap()
     {
       return new Bitmap(new MemoryStream(_payload));
     }

/// <summary>
     /// 将消息体转换成图片
     /// </summary>
     /// <returns>图片</returns>
     public Image ToImage()
     {
       return Image.FromStream(new MemoryStream(_payload));
     }

/// <summary>
     /// 将图片转换成消息
     /// </summary>
     /// <param name="playloadType">数据报文有效载荷类型</param>
     /// <param name="sequenceNumber">数据报文序列号值</param>
     /// <param name="timestamp">数据报文采样时刻</param>
     /// <param name="frame">图片帧</param>
     /// <returns>
     /// RTP消息
     /// </returns>
     public static RtpPacket FromImage(
       RtpPayloadType playloadType,
       int sequenceNumber,
       long timestamp,
       Image frame)
     {
       return new RtpPacket(playloadType, sequenceNumber, timestamp, frame);
     }

/// <summary>
     /// return the unsigned value of 8-bit integer nb
     /// </summary>
     /// <param name="nb"></param>
     /// <returns></returns>
     private static int UnsignedInt(int nb)
     {
       if (nb >= 0)
         return (nb);
       else
         return (256 + nb);
     }
   }

(0)

相关推荐

  • c#中SAPI使用总结——SpVoice的使用方法

    要使用SAPI,首先添加引用DotNetSpeech,请自行下载DotNetSpeech.dll. 初始化对象,SpVoice voice = new DotNetSpeech.SpVoiceClass(); 朗读时,使用 voice.Speak(string,SpeechVoiceSpeakFlags.SVSFlagsAsync); 暂停,使用 voice.Pause(); 从暂停中继续刚才的朗读,使用 voice.Resume(); 停止功能是大多资料都没有写清楚的,而且在网上很少能找到,这

  • C#如何通过RFC连接sap系统

    先理解一下 RFC(Romote Function Call)远程函数调用 调用前提: 1.要想通过C# 通过RFC调用SAP端,SAP端要存在RFC远程调用的函数才行(例如SAP端通过SE37创建),要不然是无法调用的. 2.C#调用RFC要有NCO DLL支持(我们使用NCO3.0,VS2013,framework2.0才行否则会报错) 注:好多人64位系统,开发的时候报错,到处找支持64位的NCO3.0,这里可以说一下,是木有的,报错是困为Framework的原因.NCO3.0只支持2.0

  • C#中调用SAPI实现语音合成的2种方法

    我们都知道现在的语音合成TTS是可以通过微软的SAPI实现的,好处我就不多说了,方便而已,因为在微软的操作系统里面就自带了这个玩意,主要的方式有两种: 1.使用COM组件技术,不管是C++,C#,Delphi都能玩的转,开发出来的东西在XP和WIN7都能跑.(要引入SpeechLib,好像在项目上点引用,然后选到系统COM吧,好久没弄,记不清楚了) 2.使用WIN7的windows api,其实最终还是调用了SAPI,所以开发出来的东西就只能在WIN7上面跑. 其实不管是哪一种,都是调用SAPI

  • C#中调用SAPI实现语音识别的2种方法

    通过微软的SAPI,不仅仅可以实现语音合成TTS,同样可以实现语音识别SR.下面我们就介绍并贴出相关代码.主要有两种方式: 1.使用COM组件技术,不管是C++,C#,Delphi都能玩的转,开发出来的东西在XP和WIN7都能跑.(注意要引入系统组件SpeechLib,XP要安装识别引擎) 2.使用WIN7的windows api,其实最终还是调用了SAPI,所以开发出来的东西就只能在WIN7上面跑. 其实不管是哪一种,都是调用SAPI,可能后一种代码比较简单. 使用第一种方式,需要注意在COM

  • RFC2702 Requirements for Traffic Engineering over MPLS

    基于MPLS的流量工程要求 (RFC2702   Requirements for Traffic Engineering over MPLS) 1. 介绍 2. 流量工程 2.1 流量工程性能指标 2.2 流量与资源控制 2.3 现有IGP控制机制的局限性 3. MPLS和流量工程  3.1MPLS导图  3.2 基于MPLS流量工程的基本问题 4.基于MPLS流量工程的增强功能 5.流量主干的属性和特征  5.1 双向的流量主干  5.2 对流量主干的基本操作 5.3 统计与性能监测 5.4

  • 使用C#实现RTP数据包传输 参照RFC3550

    闲暇时折腾IP网络视频监控系统,需要支持视频帧数据包在网络内的传输.未采用H.264或MPEG4等编码压缩方式,直接使用Bitmap图片.由于对帧的准确到达要求不好,所以采用UDP传输.如果发生网络丢包现象则直接将帧丢弃.为了记录数据包的传输顺序和帧的时间戳,所以研究了下RFC3550协议,采用RTP包封装视频帧.并未全面深究,所以未使用SSRC和CSRC,因为不确切了解其用意.不过目前的实现情况已经足够了. 复制代码 代码如下: /// <summary>   /// RTP(RFC3550

  • Golang 实现 RTP音视频传输示例详解

    目录 引言 RTP 数据包头部字段 Golang 的相关实现 结尾 引言 在 Coding 之前我们先来简单介绍一下 RTP(Real-time Transport Protocol), 正如它的名字所说,用于互联网的实时传输协议,通过 IP 网络传输音频和视频的网络协议. 由音视频传输工作小组开发,1996 年首次发布,并提出了以下使用设想. 简单的多播音频会议 使用 IP 的多播服务进行语音通信.通过某种分配机制,获取多播组地址和端口对.一个端口用于音频数据的,另一个用于控制(RTCP)包,

  • wireshark抓取本地回环数据包和取出数据的方法

    一:The NPF driver isn't running 这个错误是因为没有开启NPF服务造成的. NPF即网络数据包过滤器(Netgroup Packet Filter,NPF)是Winpcap的核心部分,它是Winpcap完成困难工作的组件.它处理网络上传输的数据包,并且对用户级提供可捕获(capture).发送(injection)和分析性能(analysis capabilities). 它不仅提供了基本的特性(例如抓包),还有更高级的特性(例如可编程的过滤器系统).前者可以被用来约

  • Android模拟器接收UDP数据包的若干问题分析

    本文实例分析了Android模拟器接收UDP数据包的若干问题.分享给大家供大家参考,具体如下: android模拟器无法接收UDP数据包 代码如下: DatagramPacket pack = null; DatagramSocket mail_data = null; byte receiver[] = new byte[100]; try { pack = new DatagramPacket(receiver,receiver.length); mail_data = new Datagr

  • python设计tcp数据包协议类的例子

    一. 问题描述 在tcp编程中,最需要解决的就是粘包分包问题.所以,我们需要在每个数据包前面加上数据包的长度用以分割粘连的包. 二. 包结构的设计 包的组成:包长度+数据域 包长度:用4个字节存储数据域长度,数据域长度即为其所占字节数 数据域:由若干个变量组成,如果是定长变量则不用加变量长度 定长变量:我们人为规定,传输中的int为4字节定长变量 变长变量:那就是字符串啦 文字难理解,那我就画个图吧: 上图的第一行是数据包的一个总体结构 第二行是数据域内部的一个结构(数据域的变量数量和位置都是我

  • 网络基础-数据包

    目录 前言 数据包简要生命周期 理解区 数据包 前言 本笔记通过记录 数据包 在网络中的生命履历来引出一些网络基础知识,如: MAC.ARP.IP.子网掩码.网关.集线器.交换机.路由器这些概念都是在链路层和网络层. (这些都不做严谨的说明,只是为了更好的了解而表达的个人描述) 数据包简要生命周期 浏览本小节的时候遇到疑问点可以可以跳到理解区 check 一下有没有答案. 数据包: 简单路径:源主机 -> 目标主机.可能路径:源主机 -> 交换机A -> 路由器A -> 路由器B

  • Fiddler如何抓取手机APP数据包

    Fiddler,这个是所有软件开发者必备神器!这款工具不仅可以抓取PC上开发web时候的数据包,而且可以抓取移动端(Android,Iphone,WindowPhone等都可以). 第一步:下载神器Fiddler,下载链接: http://w.x.baidu.com/alading/anquan_soft_down_ub/10963 下载完成之后,傻瓜式的安装一下了! 第二步:设置Fiddler 打开Fiddler, Tools-> Fiddler Options (配置完后记得要重启Fiddl

  • Python中使用scapy模拟数据包实现arp攻击、dns放大攻击例子

    scapy是python写的一个功能强大的交互式数据包处理程序,可用来发送.嗅探.解析和伪造网络数据包,常常被用到网络攻击和测试中. 这里就直接用python的scapy搞. 这里是arp的攻击方式,你可以做成arp攻击. 复制代码 代码如下: #!/usr/bin/python """ ARP attack """ import sys, os from scapy.all import * if os.geteuid() != 0:    

  • python基础教程之获取本机ip数据包示例

    这几天用到了raw socket,用python写了些demo程序,这里记录下. 首先我们看一个简单的sniffer程序: 复制代码 代码如下: #! /usr/bin/python# code for linuximport socket#s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_UDP)s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.I

  • 基于DoS攻击的随机数据包标记源跟踪算法

    作者:饥饿加菲猫(QQ120474) iojhgfti@hotmail.com 摘要: 针对互联网上日益猖獗的拒绝服务攻击(DoS),分析了传统的随机数据包标记算法的性能缺陷,提出一种新的基于散列消息鉴别码的返回跟踪算法HPPM,通过分析其性能指标,说明该算法提高了返回跟踪DoS攻击的效率和准确性. 感谢帮过我的几个高手袁哥[nsfocus], sunwear[E.S.T] , isno[xfocus] , scz[nsfocus] 1.引言 拒绝服务攻击,简称DoS(Denial-of-Ser

随机推荐