常用AMF解析

AMF(Action Message Format)简介 1、AMF简介 (1)简介 AMF(Action Message Format),即操作消息格式,基于http方式传输,是一种二进制的数据格式。主要用于数据交互和远程过程调用。它的设计是为了把actionscript里面的数据(包括Object, Array, Boolean, Number等)序列化成二进制数据,然后把这段数据随意发送给其他接收方程序,比如发给远程的服务器,在远程服务器那边,可以把这段数据给还原出来,以此达到一个数据传输的作用。 (2)AMF0和AMF3的历史 ... 阅读详情

AMF 格式是 Adobe 推出的一个二进制数据格式

AMF0 :http://wwwimages.adobe.com/content/dam/Adobe/en/devnet/amf/pdf/amf0-file-format-specification.pdf

AMF3 :http://download.macromedia.com/pub/labs/amf/amf3_spec_121207.pdf

rtmp流里分析帧类型18为AMF0类型,15为AMF3类型。
rtmp流里常用的AMF0格式有:
AMF_NUMBER 0x00
AMF_BOOLEAN 0x01
AMF_STRING 0x02
AMF_NULL 0x05
AMF_LONG_STRING 0x0C
AMF_OBJECT 0x03
AMF_OBJECT_END 0x09

解析流程:
一个字节为类型 :后面字节为数据内容
例子:
01 00
01 表示后面的值为bool , 00 为值 false

各个常用类型的解析

AMF_NUMBER :一个类型字节 + 八个数据字节(大编码)

00 41 1e 9a e4 00 00 00 00
00 表示 AMF_NUMBER
41 1e 9a e4 00 00 00 00 换算为 501433

AMF_BOOLEAN : 一个类型字节 + 一个数字字节

01 01
01 表示 AMF_BOOLEAN
01 为 true

AMF_STRING :一个类型字节 + 二个字节保存长度N (大编码) + N个数据字节

02 00 04 6d 70 34 32
02 表示 AMF_STRING
00 04 表示字符串长度为4
6d 70 34 32 换算成 “mp42”

AMF_NULL : 一个类型字节

05
05 表示 AMF_NULL 后面没有数据内容

AMF_LONG_STRING :一个类型字节 + 四个字节保存长度N(大编码) + N个数据字节

类似 AMF_STRING ,只是长度由4个字节组装

AMF_OBJECT : 一个类型字节 + N个组合字节[AMF_STRING + 一个类型字节 + 类型字节内容] + 长度为0的AMF_STRING + AMF_OBJECT_END类型字节
参考wireshark抓包内容

Name: level 为一个AMF_STRING类型,不带一个字节类型标示
String `status` 为一个AMF_STRING类型,带一个字节类型标示,也可以是带一个字节类型标示的AMF_BOOLEAN或者AMF_NUMBER

代码:
yuAMF.h

typedef enum
{
    AMF_NUMBER = 0, AMF_BOOLEAN, AMF_STRING, AMF_OBJECT,
    AMF_MOVIECLIP,      /* reserved, not used */
    AMF_NULL,
    AMF_UNDEFINED,
    AMF_REFERENCE,
    AMF_ECMA_ARRAY,
    AMF_OBJECT_END,
    AMF_STRICT_ARRAY, AMF_DATE, AMF_LONG_STRING, AMF_UNSUPPORTED,
    AMF_RECORDSET,      /* reserved, not used */
    AMF_XML_DOC, AMF_TYPED_OBJECT,
    AMF_AVMPLUS,        /* switch to AMF3 */
    AMF_INVALID = 0xff
} AMFDataType;

typedef struct AVal
{
    char *av_val;
    int av_len;
} AVal;

class uyAMF {
public:
    uyAMF(char* data , int len);
    ~uyAMF();

    bool checkout();

    AMFDataType AMF_GetType();
    unsigned short AMF_DecodeInt16();
    unsigned int AMF_DecodeInt24();
    unsigned int AMF_DecodeInt32();
    void AMF_DecodeString( AVal& bv);
    void AMF_DecodeLongString( AVal& bv);
    int AMF_DecodeBoolean();
    double AMF_DecodeNumber();
    void AMF_DecodeObject(std::map<std::string,std::string>& paramMap);

public:
    char* amf_data;
    int amf_len;
    int decode_amf_len;
};

uyAMF.cpp

uyAMF::uyAMF(char *data, int len)
:amf_data(data)
,amf_len(len)
,decode_amf_len(0)
{

}

uyAMF::~uyAMF()
{
}

AMFDataType uyAMF::AMF_GetType()
{
    decode_amf_len ++ ;
    return (AMFDataType)*amf_data++;
}

unsigned short uyAMF::AMF_DecodeInt16()
{
    if (decode_amf_len + 2 > amf_len)
    {
        return 0;
    }

    unsigned char *c = (unsigned char *) amf_data;
    unsigned short val;
    val = (c[0] << 8) | c[1];

    amf_data += 2;
    decode_amf_len += 2;
    return val;
}

unsigned int uyAMF::AMF_DecodeInt24()
{
    if (decode_amf_len + 3 > amf_len)
    {
        return 0;
    }

    unsigned char *c = (unsigned char *) amf_data;
    unsigned int val;
    val = (c[0] << 16) | (c[1] << 8) | c[2];

    amf_data += 3;
    decode_amf_len += 3;
    return val;
}

unsigned int uyAMF::AMF_DecodeInt32()
{
    if (decode_amf_len + 4 > amf_len)
    {
        return 0;
    }

    unsigned char *c = (unsigned char *)amf_data;
    unsigned int val;
    val = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3];

    amf_data += 4;
    decode_amf_len += 4;
    return val;
}

void uyAMF::AMF_DecodeString(AVal& bv)
{
    if (decode_amf_len + 1 > amf_len)
    {
        bv.av_len = 0;
        bv.av_val = NULL;
        return;
    }

    bv.av_len = AMF_DecodeInt16();

    if (decode_amf_len + bv.av_len > amf_len)
    {
        bv.av_len = 0;
        bv.av_val = NULL;
        return;
    }

    bv.av_val = (bv.av_len > 0) ? (char *)amf_data : NULL;

    amf_data += bv.av_len ;
    decode_amf_len += bv.av_len;
}

void uyAMF::AMF_DecodeLongString(AVal &bv)
{
    if (decode_amf_len + 1 > amf_len)
    {
        bv.av_len = 0;
        bv.av_val = NULL;
        return;
    }

    bv.av_len = AMF_DecodeInt32();

    if (decode_amf_len + bv.av_len > amf_len)
    {
        bv.av_len = 0;
        bv.av_val = NULL;
        return;
    }

    bv.av_val = (bv.av_len > 0) ? (char *)amf_data : NULL;

    amf_data += bv.av_len ;
    decode_amf_len += bv.av_len;
}

int uyAMF::AMF_DecodeBoolean()
{
    bool succ = *amf_data != 0;

    amf_data += 1;
    decode_amf_len += 1;
    return succ;
}

double uyAMF::AMF_DecodeNumber()
{
    if (decode_amf_len + 8 > amf_len)
    {
        return 8;
    }

    double dVal;
#if __FLOAT_WORD_ORDER == __BYTE_ORDER
#if __BYTE_ORDER == __BIG_ENDIAN
    memcpy(&dVal, amf_data, 8);
#elif __BYTE_ORDER == __LITTLE_ENDIAN
    unsigned char *ci, *co;
  ci = (unsigned char *)amf_data;
  co = (unsigned char *)&dVal;
  co[0] = ci[7];
  co[1] = ci[6];
  co[2] = ci[5];
  co[3] = ci[4];
  co[4] = ci[3];
  co[5] = ci[2];
  co[6] = ci[1];
  co[7] = ci[0];
#endif
#else
    #if __BYTE_ORDER == __LITTLE_ENDIAN /* __FLOAT_WORD_ORER == __BIG_ENDIAN */
  unsigned char *ci, *co;
  ci = (unsigned char *)amf_data;
  co = (unsigned char *)&dVal;
  co[0] = ci[3];
  co[1] = ci[2];
  co[2] = ci[1];
  co[3] = ci[0];
  co[4] = ci[7];
  co[5] = ci[6];
  co[6] = ci[5];
  co[7] = ci[4];
#else /* __BYTE_ORDER == __BIG_ENDIAN && __FLOAT_WORD_ORER == __LITTLE_ENDIAN */
  unsigned char *ci, *co;
  ci = (unsigned char *)amf_data;
  co = (unsigned char *)&dVal;
  co[0] = ci[4];
  co[1] = ci[5];
  co[2] = ci[6];
  co[3] = ci[7];
  co[4] = ci[0];
  co[5] = ci[1];
  co[6] = ci[2];
  co[7] = ci[3];
#endif
#endif

    decode_amf_len += 8;
    amf_data += 8;
    return dVal;
}

bool uyAMF::checkout()
{
    return (decode_amf_len + 1 <= amf_len);
}

void uyAMF::AMF_DecodeObject(std::map<std::string, std::string>& paramMap)
{
    AVal tmp;
    std::string val;
    std::string key;

    bool succ = true;
    while (succ)
    {
        key.clear();
        val.clear();
        AMF_DecodeString(tmp);
        printf_info("Name : %s",tmp.av_val);
        AMFDataType type = AMF_GetType();
        key.append(tmp.av_val,tmp.av_len);
        switch (type)
        {
            case AMF_STRING:
                AMF_DecodeString(tmp);
                printf_info("string : %s",tmp.av_val);
                val.append(tmp.av_val,tmp.av_len);
                break;

            case AMF_NUMBER:
            {
                double db = AMF_DecodeNumber();
                printf_info("double : %f",db);
                char data[1024] = {0};
                sprintf(data,"%f",db);
                val = data;
                break;
            }

            case AMF_BOOLEAN:
            {
                bool succ = AMF_DecodeBoolean();
                printf_info("bool : %d",succ);
                val = succ ? "true" : "false";
                break;
            }
            case AMF_OBJECT_END:
            default:
                succ = false;
                break;
        }

        paramMap[key] = val;
    }
}
NR 5G 网络功能之AMF AMF简述 接入和移动管理功能(AMF)包括以下功能。 在 AMF 的单个实例中可以支持部分或全部 AMF 功能: 终止 RAN CP 接口(N2)。 终止 NAS(N1),NAS 加密和完整性保护。 注册管理。 连接管理。 可达性管理。 流动性管理。 合法拦截(适用于 AMF 事件和 LI 系统的接口)。 为 UE 和 SMF 之间的 SM 消息提供传输。 用于路由 SM 消息的透明代理。 接... 阅读详情

相关推荐

【5G】5G 核心网(5GC)基本架构

本文旨在科普5G核心网相关知识...

Learning makes me happy (0^◇^0) 4万+

5GC 网元AMF、SMF、AUSF、UPF、PCF、UDM、NRF、NSSF、NEF介绍

接入和移动性管理功能执行注册、连接、可达性、移动性管理。为UE和SMF提供会话管理消息传输通道,为用户接入时提供认证、鉴权功能,终端和无线的核心网控制面接入点。类似于4G MME中移动性管理。AMF分配5G-GUTI,AMF选择SMF。

顺其自然~专栏 2万+

【5G核心网】5GC核心网之网元AMF

TOD

zhonglinzhang 3万+

amf解析

感觉好久没写东西了,上次写了c++利用json与flex通信后,其中一个错误,现在自己发现了,以前对AMF了解不够深刻,惭愧之至。上次说C++中接收到数据后要下移四位,其实前面那四位是AMF类型标记,准确的来说,并不一定是四位,所以这次,跟大家来讨论下AMF的数据结构。可能大家在网上找了后,发现关于AMF解析很少,甚至没有,再或者解析不够准确,那么这次,大家可参考这片文章了。 AMF是AS中的一

haihaiger的专栏 2516

RTMPdump(libRTMP) 源代码分析 3: AMF编码

注:此前写了一些列的分析RTMPdump(libRTMP)源代码的文章,在此列一个列表: RTMPdump 源代码分析 1: main()函数 RTMPDump(libRTMP)源代码分析 2:解析RTMP地址——RTMP_ParseURL() RTMPdump(libRTMP) 源代码分析 3: AMF编码 RTMPdump(libRTMP)源代码分析 4: 连接第...

dianyimo9099的博客 371

RTMP协议

RTMP协议   RTMP协议封包 由一个包头和一个包体组成,包头可以是4种长度的任意一种:12, 8, 4,  1 byte(s).完整的RTMP包头应该是12bytes,包含了时间戳,AMFSize,AMFType,StreamID信息, 8字节的包头只纪录了时间戳,AMFSize,AMFType,其他字节的包头纪录信息依次类推 。包体最大长度默认为128字节,通过chunkSiz

zhonggaorong的专栏 820

stl文件的解析和在线3d打印

什么是stl文件 STL(Stereolithography)文件,由3D Systems于1987年创建,并且已被广泛用作全行业3D打印机模型的标准文件。它有一些别的首字母缩写词如“标准三角语言(Standard Triangle Language)”,“标准曲面细分语言(Standard Tessellation Language)”、“立体光刻语言(STereolithography Language)”和“(立体光刻曲面细分语言)”。它被广泛用于快速成型、3D打印和计算机辅助制造(CAM)。STL文

weixin_39276153的博客 7304

amf0 amf3 解析

#include #include #include #include #include using namespace std; /** * the variable will be free immediately and set to NULL. * use a macro to free a variable and set to null * for example: *

zhengfl的专栏 3377

AMF.NET:轻量级AMF解析库的深度应用

在当今的软件开发领域,高性能数据通信是开发者追求的终极目标之一。AMF.NET作为一个高效的AMF(Action Message Format)解析库,在.NET环境中脱颖而出。AMF是一种二进制数据序列化格式,广泛用于Flash和Flex应用程序与服务器之间的通信。AMF.NET不仅加快了开发者的开发进程,还提高了运行效率,为.NET平台的开发者提供了一个强大的数据传输解决方案。AMF.NET的核心设计理念围绕着提高性能和兼容性。

weixin_35751194的博客 1214

AMF的概念,产生原因和特点(AMF0和AMF3)

Flash Remoting的核心技术——AMF AMF是什么?它的优点中是什么?Flash Remoting为什么选择了使用AMF而放弃了SOAP与Flash 播放器通信呢? Flash 5开始就可以以XML或者“变量/值”配对输出格式向服务器传送数据。虽然这些数据能通过Flash编译器自动解析或者通过开发人员自行编写的代码手动解析, 但解析的速度慢。因为在解析过程中,XML需要按节点逐层处理数据。而且使用XML和“变量/值”配对格式处理的数据类型只能是字符型,数字也不例外。而Flash Remoting

weixin_45750967的博客 2266

AMF协议

[教程]AMF手动解析教程 楼层直达   只看楼主更多操作楼主  发表于: 2011-04-24 易语言的AMF资料很少,所以弄个教程,GBB113的支持库要2000RMB,是用不到了 有的FLASH页游通信用AMF所以要自己解析了再编码发出去 一、AMF解析工具 1.

Vi的专栏 2720

AMF Message 及 AMF3 OBJECT 对象格式

AMF AMF是Action Message Format的简写,它是一种二进制的数据格式, 它的设计,是为了把actionscript里面的数据(包括Object, Array, Boolean, Number等)序列化成 一段你基本看不大懂的二进制数据, 然后你可以把这段数据随意发送给其他地方的程序,比如发给远程的服务器, 在远程服务器那边, 又可以把这段数据给还原出来。以此达...

611

RTMP协议中的AMF数据

这里有一个连接,amf0和amf3的库,我下了看了下,还是自己写吧,哎。http://wooce.iteye.com/blog/1396278 参考crtmpserver的代码写的,其中有amf.h文件。     AMF数据第一个byte为此数据的类型,类型有: Number 0×00 double类型 Boolean 0×01

yeyumin89的专栏 7164

python解析flv协议(AMF数据)

学习python也有1周了,因为之前学习了golang,所以觉得python和golang有很多类似的地方,比如切片和语法,python的确是一门很好的语言,至少你了解了之后才会发现其实它很强大,编写效率很高,至少目前为止我觉得运行效率也很高,之前没学过python2,所以跳过直接python3,既然是学习总得练练手吧,因为前段时间打算做一个抓直播地址的工具,截取网卡数据包的时候,接触过rtmp协...

Hi mengdj 5225

amf数据解码

这两天测试网站,发现了一个flex架构+amf协议的站点。别说注入和跨站了,连发送包和返回包的数据都看不明白,在尝试各种前端输入无果后,决定研究一下这个少见的技术组合。flex是用来做flash展示的,主要用来做页面呈现,不深究;主要是amf协议数据了。通过查询发现Python拥有amf处理模块,very beautiful,果然是强大的胶水语言,越来越喜欢Python了。接下来给大家分享一下具体

seawrath的博客 4418

AMF解析(三)

今天我们来继续AMF解析,首先,我们来讲下XML。XML(readXML):关于AMF中发送XML,都是将XML-DOC转换成字符串来发送。那解析的时候,也就成了解析字符串了。我们将XML的字符串解析出来后,利用W3C标准将字符串转换成XML(具体转换方法自己google下吧)。

1101

AMF编码

转载自:http://nkwavelet.blog.163.com/blog/static/227756038201412031720398/ AMF协议是Action Message Format协议的简称,AMF协议是Adobe公司的协议,主要用于数据交互和远程过程调用,在功能上与WebService相当,但AMF与WebService中的xml不同在于AMF是二进制数据,而xml是文本数据...

疾风剑豪 1181
zhenwu1981
博客等级 码龄10年 0粉丝 1原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值