2018
???????????????????? Android 语音通话模块介绍(一)
PJSIP简介
???? PJSIP是一个开放源代码的SIP协议栈;官网地址(http://www.pjsip.org/),它支持多种SIP的扩展功能 。PJLIB, PJLIB-UTIL, PJMEDIA, and PJSIP are released under dualopen source GPL?oralternative?license.
PJSIP包括的内容
PJSIP - Open Source SIP Stack[开源的SIP协议栈]
PJMEDIA - Open Source Media Stack[开源的媒体栈]
PJNATH - Open Source NAT Traversal Helper Library[开源的NAT-T辅助库]
PJLIB-UTIL - Auxiliary Library[辅助工具库]
PJLIB - Ultra Portable Base Framework Library[基础框架库]
PJSIP的优点
a、高度的可移殖性?
只需简单的编译一次,它能够在多种平台上运行(所有Windows系统列, Windows Mobile, Linux,所有Unix系列,MacOS?X, RTEMS,Symbian?OS,等等)。
b、极小的内存需求?
官方宣称编译后的库,完全实现SIP的功能只需要150K的内存空间,这使得PJISPi不仅仅是嵌入开发的理想平台,并且实用于那些内存运行于极小内存平台的应用,这也意味着极小的用户下载时间。
c、高效的性能?
这意味着极小的CPU运算需求下能同时实现更多的通话。
d、支持多种SIP功能及扩展功能多种SIP功能和扩展功能,例如多人会话,事件驱动框架,会话控制(presence),即时信息,电话传输,等等在库文件里得以实现。
e、丰富的文档资料
?PJSIP开发人员提供了大量的极有价值的文档资料供大家使用。
PJMEDIA简介
?PJMEDIA是一个为PJSIP建立一个完整特性SIP用户代理应用提供的补充库,这些应用包括:softphones/hardphones,gateways or B2BUA.?使用PJSIP与PJMEDIA一起开发的应用,具备如下的特性:
a、高度的可移殖性?
与PJSIP/PJLIB一起,PJMEDIA可运行在许多平台上,包括服务器、桌面、PDA系统,定制的硬件、PDA或移动电话。
b、多种功能?
会议桥接、多种编解码器、丢包隐蔽/ PLC,音频发生器,静音探测器,声学回声消除/ AEC,RFC2833,RTP / RTCP协议栈,speex/iLBC/GSM/G.711编解码器等。
c、高质量?
PJMEDIA支持频率为16KHz、32Khz的编码和解码,事实上能支持任何音频采样率,可提供高质量的采样转换。PJMEDIA也可以容忍一定量的网络或声音设备的不稳定和一些数据包丢失。
d、很好的支持嵌入式/DSP占用内存小,灵活性好。该媒体组件被设计成可替换成相应功能的硬件。
e、较好的文档资料
???PJMEDIA配备了相当不错的文档。
PJNATH简介
PJNATH是一个新的库,帮助应用程序进行NAT穿越。它实现了NAT穿越的最新规范:STUN、TURN和ICE。
PJNATH可以作为一个独立库,在您的软件中使用,也可以使用PJSUA- LIB库,该库很好的与PJSIP,PJMEDIA和PJNATH整合在一起,使用起来比较简单。
PJNATH的特点
a、STUNbis实现,
实现符合
RFC5389??标准。既提供需要使用的STUN网络接口,又提供基于STUN但更高层次的框架,既TURN和ICE。
b、NAT类型检测,
根据
RFC3489(STUN) ,在前端可以执行NAT类型检测。该检测方法不能对所有NAT类型进行穿越,但该信息可能仍然是有用,以便进行故障排除,已经被ICE整合,因此提供了该检测方式。
c、TURN实现,
?TURN是一个中继通信协议,通过使用中继,并结合ICE,提供了高效的最低代价的通信路径。PJNATH中TURN的实现,符合draft-ietf-behave-turn-14草案。
d、ICE实现,
?ICE是一个发现两个端点之间的通信路径协议。PJNATH中ICE的实现符合draft-ietf-mmusic-ice-19.txt草案
e、在未来,将实现更多的协议(如UPnP IGD和SOCKS5)。
PJLIB-UTIL简介
PJLIB-UTIL是一个辅助库,为PJMEDIA和PJSIP提供支持。这个库中的一些功能/组件:占用内存小的XML解析,STUN客户端库,异步/缓存DNS解析,哈希/加密功能等 。
PJLIB简介
q占用内存小,高性能,高可移植性的抽象库和框架,被PJSIP和PJMEDIA使用。
PJLIB是PJLIB-UTIL、PJMEDIA和PJSIP唯一依赖的库,因为它提供了完整的抽象,不仅仅是操作系统依赖的属性,还包括LIBC的抽象,并提供了一些有用的数据结构。
PJLIB基础框架库提供的功能
?内存的处理、数据的存储?
?.数据结构的(hash表、link表、二叉树、等)
.caching和pool;缓冲池和内存池
?OS抽象?
?.线程、互斥、临界区、锁对象、事件对象
.定时器?
.pj_str_t字符串
?操作系统级别的函数抽象?
?.socket的抽象(tcp/udp)
.
文件的读写
?使用前的初始化,使用后的清理
pjsip的整体框架图(图1.1)
????? 如图1.1展示了PJSIP框架的各模块,可以看出从上到下,Application(pjsua)模块可调用下层所有的模块,也即是PJSUA处于最高层,其整合了下层模块的全部功能以
这也就是为什么我们基本的操作都在PJSUA这里进行。是因为通过PJSUA,我们就能很方便的深入到其他模块中。接着Application模块往下就是PJSUA_lib层,要让应用层(
PJSUA)能更好的调用,当然得有个封装好的库,这个库就是PJSUA_LIB库,称为高层用户代理库,集合SIP,Media以及NAT穿越,所以也就有了往下的PJMEDIA-CODEC和PJMEDIA(负责SDP协商媒体编码和媒体传输),PJNATH(解决NAT穿越),PJSUA-UA(提供SIP用户代理库),PJSIP-SIMPLE(实现presence和及时消息),PJSIP(核协议栈,SIP协议),PJLIB-UTIL(提供有用的工具函数)以及PJLIB(每个功能根据其所在的层次以及负责的功能提供丰富的接口)等模块。
???????从实现上来看,最上层为应用层,该层将在Android SDK的框架内,采用Java语言来实现;第二层为JNI层,SIP协议栈有很多种实现,其中,采用C语言的SIP协议栈在效
、速度、系统占用方面有着超越其他库(如Java协议栈)的优势,因此,该方案将在第三层采用纯C语言实现的PJSIP协议栈。为了让Java应用层能调用协议栈层,在两层之
间需要一个衔接的桥梁,这就是JNI层。最后一层是驱动层,这部分一般是由手机厂商来实现的,此处将不做重点介绍。
?SIP协议栈及UA
??? SIP协议栈直接关系到整个系统的质量与效率,许多开源项目基本上都是采用纯C语言开发的PJSIP库。该库采用C语言开发,且源码开放,在兼容性与效率上有明显优势,不仅体积小(完整的SIP封装也不过150 KB),同时还实现了一个内存池,使得安全系数与运行效率大为提高
PJSIP协议栈
????? ?PJSIP协议栈遵循标准的SIP协议,采用分层架构:SIP/SDP消息编码解析层、传输管理层、SIP终端、事务层、会话层以及应用层等。由于SIP协议采用文本消息发送请求和响应,所以首先需要将SIP消息按照巴斯克范式(ABNF)编码和解析,这就是SIP/SDP消息编码解析层所完成的功能。传输管理层用来管理用户代理与服务器之间的请求和相应;SIP终端是PJSIP中转机制的实现,它主要负责管理各个SIP组建,例如像SIP终端实例注册组件,分发消息到事务层、会话层及应用层,回传处理结果,管理定时器、I/O队列等;事务层通过状态机机制管理SIP信令,每一次状态机状态的改变都将触发回调函数;会话层负责会话的发起与响应,一般与应用层结合在一起,用于用户交互,不同的平台有不同的实现,这里主要使用Andriod的GUI来实现。
?? PJSIP是一个高度封装的库,实际上它是通过PJSUA子库来实现应用的。一个完整的PJSUA生命周期,首先需要初始化,通过函数init()来实现。在这个函数中,将创建代理、初始化变量和堆栈,以及创建一个UDP传输并在最后启动代理;第二步将为UA添加用户,如果需要的话,还要向服务器注册用户;当用户添加成功后,此时可以建立一个呼叫连接,发起会话;当会话连接成功后,就可以使用SRTP协议实时传输加密后的数据,进行通话。最后的过程是挂起或销毁呼叫。
UA原理
UA(User Agency)是协议栈的具体实现,PJSIP通过封装了的PJSUA来实现,在这一点上,大部分的SIP库都大同小异,在此将介绍UA的工作原理。
一个典型的UA包含UAC(User Agency Client)和UAS(User Agency Server)两部分。会话由UAC发起。当呼叫发起时,UAC将首先发送“IN-VITE”消息给SIP代理服务器,服务器收到“INVITE”消息后将返回一个应答“200 OK”,并回答“ACK”进行确认,同时通知主叫用户(即会话发起用户)上线通话。如果主叫端(用户端)主动结束会话,UAC将返回“BYE”消息,同时通知服务器;如果用户端收到服务器传来的“BY-E”消息,回答“200”,并结束会话。
服务器端,
UAS收到UAC(用户端)发来的“INVITE”消息,首先从消息中提取出主、被叫对象,然后检查当前是否有空闲信道,若没有则返回“486 BUSY HERE”(即系统忙)消息;接着将检查被叫用户是否在服务区,如果被叫对象不在服务范围,则返回“404 NOT FOUND”(即用户不在服务区);若被叫用户成功上线,则返回“200 OK”,同时准备开始会话。
SIP协议栈一般使用SIP统一资源定位符(URL)来标识,它根据URL来寻址,如集群用户“200”,“300”分别对应SIP用户为“200@192.168. 1.100”,“300@192.168.1.100”。本文中也使用这种方式来测试通信。
Pjsip实例分析
?代码:simple_pjsua.c
/**
* simple_pjsua.c
*
* This is a very simple but fully featured SIP user agent, with the
* following capabilities:
*? - SIP registration
*? - Making and receiving call
*? - Audio/media to sound device.
*
* Usage:
*? - To make outgoing call, start simple_pjsua with the URL of remote
*? ? destination to contact.
*? ? E.g.:
* simpleua sip:user@remote
*
*? - Incoming calls will automatically be answered with 200.
*
* This program will quit once it has completed a single call.
*/
#include
#define THIS_FILE"APP"
#define SIP_DOMAIN"example.com"
#define SIP_USER"alice"
#define SIP_PASSWD"secret"
/* Callback called by the library upon receiving incoming call */
staticvoidon_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
? ? pjsip_rx_data *rdata)
{
? ? pjsua_call_info ci;
? ? PJ_UNUSED_ARG(acc_id);
? ? PJ_UNUSED_ARG(rdata);
? ? pjsua_call_get_info(call_id, &ci);
PJ_LOG(3,(THIS_FILE,"Incoming call from %.*s!!",
(int)ci.remote_info.slen,
ci.remote_info.ptr));
/* Automatically answer incoming calls with 200/OK */
pjsua_call_answer(call_id,200, NULL, NULL);
}
/* Callback called by the library when call's state has changed */
staticvoidon_call_state(pjsua_call_id call_id, pjsip_event *e)
{
? ? pjsua_call_info ci;
? ? PJ_UNUSED_ARG(e);
? ? pjsua_call_get_info(call_id, &ci);
PJ_LOG(3,(THIS_FILE,"Call %d state=%.*s", call_id,
(int)ci.state_text.slen,
ci.state_text.ptr));
}
/* Callback called by the library when call's media state has changed */
staticvoidon_call_media_state(pjsua_call_id call_id)
{
? ? pjsua_call_info ci;
? ? pjsua_call_get_info(call_id, &ci);
if(ci.media_status==PJSUA_CALL_MEDIA_ACTIVE) {
// When media is active, connect call to sound device.
pjsua_conf_connect(ci.conf_slot,0);
pjsua_conf_connect(0, ci.conf_slot);
? ? }
}
/* Display error and exit application */
staticvoiderror_exit(constchar*title, pj_status_t status)
{
? ? pjsua_perror(THIS_FILE, title, status);
? ? pjsua_destroy();
exit(1);
}
/*
* main()
*
* argv[1] may contain URL to call.
*/
intmain(intargc,char*argv[])
{
? ? pjsua_acc_id acc_id;
? ? pj_status_t status;
//? 创建PJSIP
/* Create pjsua first! */
? ? status=pjsua_create();
if(status !=PJ_SUCCESS) error_exit("Error in pjsua_create()", status);
//? 校验被叫SIP地址是否正确
/* If argument is specified, it's got to be a valid SIP URL */
if(argc >1) {
status=pjsua_verify_url(argv[1]);
if(status !=PJ_SUCCESS) error_exit("Invalid URL in argv", status);
? ? }
//? ? 初始化PJSUA,设置回调函数
/* Init pjsua */
? ? {
pjsua_config cfg;
pjsua_logging_config log_cfg;
pjsua_config_default(&cfg);
cfg.cb.on_incoming_call=&on_incoming_call;
cfg.cb.on_call_media_state=&on_call_media_state;
cfg.cb.on_call_state=&on_call_state;
pjsua_logging_config_default(&log_cfg);
log_cfg.console_level=4;
status=pjsua_init(&cfg, &log_cfg, NULL);
if(status !=PJ_SUCCESS) error_exit("Error in pjsua_init()", status);
? ? }
//? ? 创建PJSIP的传输端口
/* Add UDP transport. */
? ? {
pjsua_transport_config cfg;
pjsua_transport_config_default(&cfg);
cfg.port=5060;
status=pjsua_transport_create(PJSIP_TRANSPORT_UDP, &cfg, NULL);
if(status !=PJ_SUCCESS) error_exit("Error creating transport", status);
? ? }
//? ? 启动PJSIP
/* Initialization is done, now start pjsua */
? ? status=pjsua_start();
if(status !=PJ_SUCCESS) error_exit("Error starting pjsua", status);
//? ? 设置SIP用户帐号
/* Register to SIP server by creating SIP account. */
? ? {
pjsua_acc_config cfg;
pjsua_acc_config_default(&cfg);
cfg.id=pj_str("sip:"SIP_USER"@"SIP_DOMAIN);
cfg.reg_uri=pj_str("sip:"SIP_DOMAIN);
cfg.cred_count=1;
cfg.cred_info[0].realm=pj_str(SIP_DOMAIN);
cfg.cred_info[0].scheme=pj_str("digest");
cfg.cred_info[0].username=pj_str(SIP_USER);
cfg.cred_info[0].data_type=PJSIP_CRED_DATA_PLAIN_PASSWD;
cfg.cred_info[0].data=pj_str(SIP_PASSWD);
status=pjsua_acc_add(&cfg, PJ_TRUE, &acc_id);
if(status !=PJ_SUCCESS) error_exit("Error adding account", status);
? ? }
//? ? 发起一个呼叫
/* If URL is specified, make call to the URL. */
if(argc >1) {
pj_str_t uri=pj_str(argv[1]);
status=pjsua_call_make_call(acc_id, &uri,0, NULL, NULL, NULL);
if(status !=PJ_SUCCESS) error_exit("Error making call", status);
? ? }
//? ? 循环等待
/* Wait until user press "q" to quit. */
for(;;) {
charoption[10];
puts("Press 'h' to hangup all calls, 'q' to quit");
if(fgets(option, sizeof(option), stdin)==NULL) {
puts("EOF while reading stdin, will quit now..");
break;
}
if(option[0]=='q')
break;
if(option[0]=='h')
? ? pjsua_call_hangup_all();
? ? }
/* Destroy pjsua */
? ? pjsua_destroy();
return0;
}
simple_pjsua.c的main函数主要流程:
这里可以分析一下它的代码及流程图:
1、一开始是回调使用的函数,例如on_incoming_call当来电话的时候,pjsip会自动去调用你写的这个函数,前提是你在初始化pjsua的时候设置了on_incoming_call?=&on_incoming_call,
2、error_exit退出应用所需要的操作
3、main函数:
?(1)pjsua_create()创建pjsua的第一步,如果是要打电话要确认URL是否是正确的pjsua_verify_url
?(2)初始化pjsua,pjsua_config_default(&cfg)来初始化配置,然后设置一些回调函数,设置日志,最后初始化pjsua_init(&cfg, &log_cfg, NULL);
?(3)创建UDP的传输,设置端口号
?(4)接下来就是启动pjsua,通过pjsua_start();
?(5)创建账户,这个是重点所在,pjsua_acc_config_default初始化配置,然后设置相关的内容,id对应这url,realm是服务器的域名,还有密码和用户名,最后调用?pjsua_acc_add(&cfg, PJ_TRUE, &acc_id);来实现帐号的注册。
4、打电话,上面也提到过,你打电话的话需要验证URL是否正确的?pjsua_verify_url,然后调用pjsua_call_make_call来打电话。
5、挂电话,调用?pjsua_call_hangup_all();
6、最后销毁,pjsua_destroy();
40年前,江苏省的一个田野间传来了一阵惊呼声,不多会儿就来了密密麻麻的一群人。
远远望去,一群人围成了一个大圈,隐隐约约还可以听到人群中在不断地窃窃私语。
他们究竟在看什么呢?故事还要从改革开放初期说起……
一、庄稼地里的金子
20世纪70年代的时候,我国刚刚进入改革开放,全国上下的经济状况都还比较落后。
在江苏省境内有一个盱眙县,农民的生活非常的困苦:土壤贫瘠造成农作物收成低下,灌溉问题也完全依靠老天爷。
陷入此等困境,农民们绝望极了,他们急需一个人能给予他们帮助。
1982年,转折到来!
这一年,在当地生产队的领导下,盱眙全县村民准备开挖水渠,走出迈出美好生活的第一步。
可是,开挖水渠可不是一件简简单单的事,尤其是在那个技术落后的年代,所有的工作都需要人力来完成。
吃饱穿暖面前,困难一点又怎样?
就这样,自盱眙县的村民们接到命令的那一刻开始,他们便开始着手准备这项棘手的工程。
开挖的第一天,每家每户的青年壮丁几乎都来到了现场,个个摩拳擦掌准备大干一场。
眼看人到得差不多了,生产队队长数了数人数,发现人数好像不对。
“有谁看见老万家父子了?”
大伙纷纷摇头。
生产队队长看着太阳马上就出来了,再不开始干活天就越来越热了,便带领大家边干边等。
等到快中午的时候,远处缓缓走来了两个男人,不是别人,正是万家父子。
走近一看,两个人带着惺忪的睡眼,仿佛刚从睡梦中醒来。
见状,生产队队长走上前去问道:“老万,你说说你怎么回事,不知道今天咱们有任务吗,大家都来了,就你们家没来。”
年纪大点的父亲听了生产队队长的话,非但没有感觉有一丝惭愧,反而还振振有词道。
“队长,不是我们不想来,你们这挖水渠可是毁了我们的庄稼啊。”
万家儿子趁机附和道:“对啊队长,国家管不管赔偿我们家啊。”
看着万家父子这般样子,生产队队长知道有什么道理和他们也是讲不明白的,便默不作声地递给了他们铁锹和锄头。
看着面前的铁锹和锄头,老万带着儿子极不情愿地接了过来,朝着人群中走去。
众人看到万家父子到了日上三竿才过来,不免有一些意见,人群中也都在怨声载道。
“来得这么晚,不如去那块硬地挖水渠吧。”
老万看乡亲们都不想和他们一块干活,自己正好也不想听他们在这里嚼舌根,便带着儿子去了另外一块地挖水渠。
巧的是,万家父子现在所在的这块地就是乡亲们刚刚讨论的那块硬地,难道这块地有什么特殊之处吗?
不一会,老万便发现了这块地的“玄机”,因为它真的是“人如地名”,比其他的地方坚硬了好几倍。
老万挖着挖着就知道了其中的缘由,这块地的下方并不是松软的土壤,而是一层厚厚的石头。
看到这里,老万心里更气愤了:这群村民竟然存心作弄自己,老子可不干了。
于是,他一下子就把手里的工具扔得远远的,坐在地头歇息。
“爸,爸,你快来看,这是什么。”
老万正在生气,听见儿子的喊声也一动不动,回答道:“你自己挖吧儿子,你爹我是不行了。”
儿子看见爸爸一动不动,气急败坏地跑了过来,拉着老万就跑到了自己刚才挖地的附近,指着地上的一个物件。
老万定睛一看,这庄稼地里竟然长出了一块金豹子和一个“破”瓶子。
此时,老万下意识地忽略掉“破”铜壶,眼里只剩金豹子,毕竟这个金豹子看着就会很重,一定很值钱。
想着想着,老万陷入了沉思……
与此同时,儿子看着爸爸一言不发,以为爸爸是吓傻了,急忙推了推老万的肩膀说道:“爸,我去把队长喊来吧。”
听到这话,老万瞪了儿子一眼,怒嗔道:“傻小子,告诉他干什么,咱们抱回家去,指定能卖不少钱呢,还能给你娶媳妇用。”
于是,父子二人开始挖这个宝贝。
挖之前,他们也没想到竟埋得那么深,万家父子二人挖了大半个小时才使得这块金疙瘩和铜壶完全露了出来。
从外观看,这块金子和铜壶放在一起是有造型的,但是具体是什么东西,老万一时半会还想不起来。
彼时,万家父子四处看了一下,没有人注意到这里,便把外套脱了下来,准备包裹着它带回家中。
可是,等到要搬出土坑的时候,他们才发现这两个东西非常的重,一只手根本就搬不起来,更别说藏在怀里带出去了。
就在万家父子两人想尽办法将这个金疙瘩连带着这铜壶藏在怀里的时候,生产队队长突然走了过来。
走上前来,队长发现老万这怀里鼓鼓囊囊的,便问道:“老万,你这怀里拿的是什么,快点交出来。”
老万哪肯束手就擒,嘴硬地说什么也没有。
队长看看老万软硬不吃,便开始跟他儿子讲道理:“孩子,如果你爸偷了什么东西,你免不了也是要遭殃的。”
听了队长的话,小万害怕极了,急忙把东西从父亲怀里夺了出来,原封不动地递给了队长。
队长本以为他们两人捡了一些钱财,没想到竟然是这么大的两个物件。
看着这个金豹子和旁边看起来破破的铜壶,生产队队长陷入了沉思:盱眙县虽然只是江苏省一个非常不起眼的小城市,但是这座县城建县于秦已有两千多年的历史了,会不会是文物?
想到这里,生产队队长觉得这很有可能是一件文物,不能轻举妄动。
于是,他立刻喊过来其他村民一起抱回了生产队,最后,经过一番折腾,他们发现这个金豹子重18斤。
见到这样的结果,队长更加肯定自己的猜想,安排一番后,就准备向市里的领导汇报。
二、银行里的交易品
没过多久,这件事就在整个盱眙县城传开了,而且传言越来越多,也越来越不切实际。
有的人说这是古代皇上的陪葬物,甚至还有的说这个是金豹子转世化身而来的,但是无论大家说什么,老万心里都是不相信的。
因为他始终认为生产队队长想要独吞这件宝贝,这块金子是从他们万家地里挖出来的,肯定应该归自己所有。
想到这里,老万终于忍不出了,偷偷地去了生产队。
他去到生产队的时候,生产队正好没人,于是,他趁着“千载难逢的好机会”,把“金豹子”又抱回了自己的家中。
回到家,老万心想:“如果一直把这个物件放在家中,早晚有一天会被生产队队长发现的,不如在他发现之前给变现了,到时候就算让他知道了也无计可施。”
想到这里,老万立刻就把“金豹子”放在摩托车上向县城的方向奔去,一路上既紧张又激动。
路上,老万心里止不住的乐:
“我们老万家说不定马上就要成为这盱眙县首富了,看以后谁还敢看不起我们。”
到了县城以后,老万也不知道应该去哪里变卖,有现钱的地方老万只想起了银行,于是就抱着他的“金豹子”走了进去。
没想到的是,从他踏进银行的第一步开始,他就已经暴露了。
有一个银行职员看到这个农民大哥手里一直紧紧地抱着这个奇怪的东西,不免好奇地问他是否需要什么帮助。
老万神神秘秘地回答道:“把你们经理喊过来,我有一笔大买卖要跟他做。”
银行职员听到这里更加疑惑了,但是也只好把经理请了出来。
经理来了以后,一眼便明白了老万的意思,他自然也知道这肯定是国家文物,交易文物是违法的。
于是,经理开始问这个“金豹子”是从哪里来的。
对此,老万自豪地说:“这是我们家地里挖出来的,肯定是祖上给我们留下的宝贝。”
老万的话更加坚定了经理内心的想法,他现在只能想办法拖住这位农民大哥,把消息上报给国家。
正在这时,生产队队长也过来了银行,原来市里面的领导已经去了他们村里,却没有看到这件所谓的“金豹子”。
队长一想便知肯定是老万拿走了,在对小万的百般追问下才得知他爸爸骑摩托车来了县城的银行。
就这样,生产队队长带着老万,老万带着“金豹子”,一起回到了村里见到了市里的领导。
领导们听完“金豹子”事件的整个来龙去脉,不禁啼笑皆非,但是看在老万没有上过一天学的份上,便没有追究责任。
三、南京博物院的镇院之宝
后来,这件“金豹子”便被盱眙县公安局当作文物存放在了银行的金库中,并且还把这一事件登报分享给了大家。
这则快讯在报纸上发表不久就被南京博物院院长看到了,看着报纸上的图片,他隐隐约约觉得这个“金豹子”还隐藏了更大的玄机。
于是,这位院长便专门派了文物专家前来鉴定,不曾想,确实发现了这“金豹子”下面的秘密。
据南京博物院考古所的研究员介绍,用“金豹子”来称呼这个金兽似乎也有一些不妥。
因为,“金豹子”也只不过是宝物的一个盖子,真正的宝物是它下面的那件陈璋圆壶。
这陈璋圆壶内藏着许多古代的黄金铸币,更令人可喜的是,陈璋圆壶在地里埋了这么多年,竟也没有受到任何损伤,外观精美绝伦,包含着非常高的历史价值和艺术价值。
这样的工艺绝对不会出自普通人家,那么具体是出自哪朝哪代?刚开始的时候,专家们也不清楚,直到他们开始注意陈璋圆壶外的铭文。
在专家们逐渐地鉴定和探寻中,这件战国错金银重络铜壶的秘密也慢慢浮出了水面。
最终,经过查证,这件器物并非是普通的贵族器物,而是燕国的国器,铭文的内容也都记载了齐国攻占燕国的国都,并且将国器掠夺走的整个事件。
此外,这件历史事件在《史记》《战国策》等一些史书里都有记载,所以这个陈璋圆壶的历史是有章可循的。
现在,“金豹子”和“铜壶”已经被定性为国宝级别文物,成为了南京博物院的镇院之宝。
参考资料
《战国错金银镶嵌丝网套铜壶》中新网【引用日期2018-08-16】
《错金银镶嵌丝网套铜壶—禁止出国(境)展览文物》中国社会科学院考古研究所
《战国错金银镶嵌丝网套铜壶》百度百科
下一篇:“别再联系了。”
发表评论