当前位置:  编程技术>移动开发
本页文章导读:
    ▪浅谈Java游戏发动机在智能机领域的发展        浅谈Java游戏引擎在智能机领域的发展1.为什么专注于Java而不是C/C++? 一、首先,Java人讨厌C/C++ 对任何一名忠实的Javaer来说,我们都不会喜欢复杂的C++代码结构,都不会喜欢解决那些因繁琐.........
    ▪ 【RTP】 入门实践小结【精华】        【RTP】 入门实践总结【精华】一,windows 下资料       http://www.cnblogs.com/skyseraph/archive/2012/04/07/2435540.html 一,安装Cmake 二,在 jrtplib-3.9.1_1 中运行 cmake . 生成Makefile 三,然后 make         接着.........
    ▪ Hibernate框架笔记(下)       Hibernate框架笔记(上)Hibernate文档笔记共分为二个部分,此处是第一部分,讲述了Contextual Sessions、Configuration、获取SessionFactory和JDBC Connections(Session是对JDBC连接的封装)。 五、Contextual Session.........

[1]浅谈Java游戏发动机在智能机领域的发展
    来源: 互联网  发布时间: 2014-02-18
浅谈Java游戏引擎在智能机领域的发展

1.为什么专注于Java而不是C/C++?

一、首先,Java人讨厌C/C++

对任何一名忠实的Javaer来说,我们都不会喜欢复杂的C++代码结构,都不会喜欢解决那些因繁琐的指针、引用所衍生的神奇Memory问题,更难以接受代码和资源稍微多些,重新编译一次工程就要耗费数分钟乃至数小时的恐怖煎熬。

尽管Java语法脱胎于C/C++,且现阶段在运行上也离不开C/C++构建的JVM。但我们却真的不喜欢直接用C/C++编程,否则,也不会选择这条与C相似,却不尽相同的道路。

坦率地说,绝大多数Java人对于C/C++有着本能般的排斥,就连JNI开发方式,我们也会尽量少的使用。

强迫我们使用C/C++会让我们非常痛苦,强迫我们在非必要的场合使用C/C++简直让我们想去犯罪。

比如,小弟在Libgdx论坛“潜伏”时,就曾看到有Javaer对某C系游戏引擎大声疾呼:I hate it!

小弟在此敬告所有专职搞C的女同志:多年后,我若搞Java,你若玩C/C++, 让你闺女还有你在路上注意点(╯^╰)。

二、其次,C/C++在游戏开发上也有其局限性

虽然从运行效率上看,C系语言编写的游戏会比Java语言编写的游戏运行效率为高。然而,这却是以单纯C/C++开发的低兼容性,高难度,漫长开发周期为代价的。

可能有人会说:别扯了,张嘴你丫就胡说!C/C++不是能“一次编写,到处编译”吗?怎么会扯到兼容性问题上呢?

——拜托,有脑子的话,请让它稍微运动一下好吗?

如果C++真的能“一次编写,到处编译”,当年Sun为又凭什么让Java一举成名,最高市值达到2100亿美金的巅峰?如果C++真的能“一次编写,到处编译”,那苹果如今又为什么要搞LLVM这个“特殊的虚拟机”出来(虽然对外仅仅是“资助”关系),补足IOS系统呢?

关键原因就在于,单纯C/C++开发对系统底层的依赖实在太高,太高了。以至于,只要底层稍有变动,单纯的C/C++项目就随时可能瘫痪死掉。

远的不提,就说当初Android 4.1升级那么一次,顷刻便干躺下一片C/C++游戏引擎,他们的作者一直要耗到数周乃至数月后升级引擎代码才勉强解决了兼容问题。然而,基于Dalvik的Java应用们,则普遍不存在这种困扰,甚至对此事根本毫无觉察。

对Java来说,无论系统底层如何修改,只要上层虚拟机的API不换,应用都可以准确无误的运行下去。退一万步讲,即使部分后台源码被更换了,对我们而言通常也就是换个类,甚至换个函数名的事。然后C/C++却不一样,C/C++在开发上牵一发而动全身,一个指针的错误使用,都可能让你的程序在莫名其妙的时刻莫名其妙的崩掉。更何况是不知牵扯到何处的底层变动了,将遭遇到的种种问题,远比Java用户所能遭遇到的问题要多得多。

或者有人会说,我用的C/C++引擎很高级,是源自YYYY的ZZZZ,或者山寨自OOOO的XXXX,他们有数十人的专业团队,有上千万的资金支持,所有可能的问题都已经被他们解决了,用他们的C/C++引擎——绝对不存在任何兼容性问题。

那么,小弟只反问您一句,就一句话。

就算他们能做到,您确信,您也可以做到吗???

事实上,即便你所使用的C/C++引擎本身没有任何兼容问题,但作为C/C++引擎用户的你,在C/C++开发中,也能做到绝对不产生兼容性问题吗? 

要知道,用C++开发时,只要稍不留神,手轻轻那么一滑,就可能写出在这个平台能用,那个平台不行的代码来,而你书写的代码量越大,这种可能性也就变得越高。

小弟愚见,在这世上号称可以多平台运行的语言中,有两种最为悲剧,一者为C/C++,一者为JavaScpirt。

让这两个家伙跨平台运行的代价,在写过一定数量的跨平台代码后恐怕都会印象颇深吧?虽然他们在最终的最终,确实可以实现所谓的“跨平台运行”,但这中间的艰辛困苦,又有几人明了?真是“光看见贼吃肉,没看见贼挨打”啊!

仔细说来,为什么C/C++游戏引擎大多会青睐于Lua,AngelScript这些脚本引擎?为什么即使C/C++的功能已经十分完善,还要将它们引入其中,就像生怕你们使用C/C++而非脚本来进行开发一样呢?

这里的潜台词恐怕是“大哥,大姐们,兄弟好不容易才搞定这个C/C++引擎支持多平台运行,你们玩玩脚本就好,可千万别改我的C/C++代码啊!千万别改!你们一改,一改,就该改崩了~”

所以,即使你代码写的再好,只要使用C/C++开发,一旦所在平台底层代码有了变动,就绝对逃不出“一次编写,到处编译,平台升级,编译失败,重新编写,重新编译,平台又改,循环重来……”的变态连锁,这无疑是其低兼容性的体现。

总之水很深,不提也罢(-____-)。

再者,C/C++编译之耗时大家有目共度,而且代码越多耗时越大,对于代码量小的简单项目还好说,您大可以做会眼保健操什么的等待它结束。而一旦处理代码和资源都较多的中等以上规模项目(比如搞个怪物猎人4之类),您又偏偏喜欢按下【重新编译】而非【编译】按钮。那么,您真的可以扭头回家,等明天再来看有啥编译结果吧(结果第二天一看,一万多个编译错误,十几万个警告之类(° ?°)~)

小弟经常在想,如果Windows7或8是某个人单独负责的项目,而他又将所有开发资源都引入一个Project中,那么他每次按下重新编译,是不是公司都会给他放一次大假呢?\(╯-╰)/

由此可见,C/C++作为游戏开发语言,远非大家想象中那么十全十美。

三、最后,脚本语言才是游戏开发的王道,而Java本身就是很棒的脚本

通过前文的论述,大家可以发现,即便在今天,大多数C/C++开发的游戏引擎若没有像lua这类脚本引擎相配合,也很难制作出多么复杂的游戏来。

也正因为有了Lua,AngelScript之类的脚本引擎,才让C/C++的游戏开发周期由【数年】缩短为【数月】,才有效减少了C/C++程序员对代码的反复编译调试,才可以让脚本动态调用C/C++写成的基础类库,从而拓展出崭新的高级功能,而不必考虑一改就不兼容的问题……

可以说,有了脚本语言,才局部解决了上述所涉及的纯C/C++开发问题。

脚本引擎的诞生,缩短了C/C++游戏的开发时间,提高了代码的重用可能,使得大中型C/C++游戏能够较为轻松的实现。对于C/C++开发的游戏引擎而言,lua这样的脚本引擎真的至关重要,更可以说是无可替代。

然而,如果我们用Java来制作游戏引擎呢?我们还需要这样的脚本引擎辅助吗?

——答案,当然是,不需要了!

显而易见的,对于Java开发者来说,Lua肯定没有对于C/C++那么重要。或者说,Java在某种程度上讲,本就是和Lua平级的东西(Java有编译过程,产生Bytecode,但同时又使用虚拟机解释Bytecode执行,解释执行是脚本语言的特性,故此严格意义上说Java等于解释+编译共存,单纯把它当脚本用没什么)。

譬如我们以Java开发时,哪怕重新编译上万个class,也不过是一瞬间的事情,这是编译CPP的速度所无法比拟的,脚本才有这种优势。而Java语法又比C/C++简洁很多,只要掌握一些基本方式,任何人都能用它轻易开发游戏(Java游戏存世量少,是最初Java开发偏向JavaEE造成的,而不是Java不适合做游戏,否则就不能解释海量JavaME游戏的存在(另,拆过一些工程发现,有些排行很高的IOS游戏纯是JavaME游戏换图移植|||))。

我们完全可以说,以Java代码充当游戏脚本,和使用lua脚本是没有本质区别的;即使偏要说有,也只是lua+java可能会让开发变得更慢,而非更快,毕竟很多面向对象的特性lua并不具备。

现实中的例子也是这样,著名的Unity3D引擎当前总共支持三种开发语言:JavaScript,C#,Boo,而其最常用到的C#,在各种意义上都和Java平级。更进一步讲,只要Unity3D愿意引入IKVM,它便可以立刻支持Java开发(Unity3D基于Mono,所以能凭借IKVM做Java支持)。

假如您认为Unity3D在设计上不算脑残的话,那么使用Java做为游戏开发语言便同样是最正常不过的选择。

——当然,有两种特殊状况存在:一是您要移植已经使用lua引擎的游戏项目,二是您需要和他人分工开发,但对方却只会lua脚本。那就另当别论。

但Java世界中还有Groovy和Scala等更加易用的动态语言项目存在,就算有人认为新一代动态语言相比老旧的Java更为高效,也大可用它们直接补上,而不必借助lua。

综上所述,利用Java充当游戏脚本,充当游戏开发语言绝不是什么奇谈怪论,而是非常容易做到,也必将做到的事情。

2.Java游戏引擎前进的道路上面临着哪些障碍?

有优势当然也会有劣势,在智能机领域中,Java游戏引擎所面临的问题也真不少,否则早该由Java语言一统天下,而论不到C/C++逞强撒野了。

一、Oracle不给力,标准Java目前不能支持任何一款知名智能机平台

假如Oracle提供多智能机平台支持,让Java游戏爆炸式增长,根本就轻而易举。MonoTouch就放在那里,Java多平台支持根本不会存在技术障碍,真做不了还可以买下MonoTouch换壳嘛。

真正的大问题是,Oracle似乎对移动领域根本就没有兴趣(至少在行动上),以至平白错过了智能机发展时代,还懵懂未明。

悉数目前最有发展潜力,也最知名的三大智能机平台,莫过于:IOS、Android、WP(我是Blackberry、MeeGo、Bada脑残黑)。

抛开Oracle主观意图不谈,我们只说凭借Oracle多年来积累下的“江湖地位”, Java究竟能部署到哪一个上呢?

Google的Android?100%不可能。

世人皆知,Google已经让埃里森得罪苦了(犹太人别打犹太人啊~),标准Java想上Android不说是做梦,但除非Oracle和Google全体员工同老板一起嗑药,然后一起滚床单高喊Yooooooo。否则,这也算得上天方夜谭了(何况Google自己的Dalvik还活着呢)。

Microsoft的WindowsPhone?90%不能实现。

至于WP平台,额滴神啊,人家Microsoft有自己的.Net,怎么轮得到Java插手。假如我是埃里森,倒很可能拼着丢个几亿$出去买下Mono,然后闭源C#部分,让它彻底沦为Java项目再开源,同时免费MonoTouch三年,真不信搞不定WP(三年后考下Oracle认证的可以免费用,考不下的一年99$使用费~)。

可惜,埃里森成不了我,我也成不了埃里森,所以,全是做梦。

Apple的IOS?听说埃里森和天国的乔布斯,当年私交好到两人老婆都妒忌啊。

仔细斟酌下,小弟发现以Oracle的人缘+江湖地位,Java现阶段唯一有可能上的知名智能机平台(个人愚见,Blackberry真心不算智能机,没有911这货不可能成功),似乎只剩下Apple的IOS了。

尤其在很多年前,当JavaFX 2.0刚刚出现之时,就有人迫不及待的上传了下面这样一张图片。不得不说,当时很多Javaer都倍感鼓舞,以为Java终于能跑在IOS上了。

“岁月是把杀猪刀,喝了咖啡,黑了龟壳,收了老乔”

但接下来的JavaFX发展,却让人不再乐观,尽管人们都期待着看到JavaFX跑在IOS上的飒爽英姿。但换来的,却是Oralce一次又一次的疯狂跳票。

从2009年-2012的JavaOne,几乎JavaFX on IOS的字眼就从没间断过,如今已近2013年了(如果2012年地球不便当),传说中的JavaFX on IOS 却连个测试版也没有踪影。

此刻我们再看Oracle公布的Java发展路线图,连IOS的影子都找不到了。

大哥,把你手里IPad中运行的JavaFX项目上传先,都三年了。此刻我只能说——毫无PS痕迹啊。

Oracle啊!Oracle!你真不愧是传说中的坑神,专注坑爹30年!画个圈圈咀咒你(╰_╯)

二、自行开发Java多平台支持标准不统一,各师各法

因为Oracle跪了,Javaer们不得不纷纷自谋生路,自己想办法解决Java应用的智能机移植问题。

不过嘛,这也没什么,Mono并非Microsoft官方开发,照样可以干的风生水起。

——我们坚信,技术宅挽救世界。

遗憾的是,目前在Java世界中,还没有一款能同Mono并驾齐驱的项目,更缺乏一个Xamarin那样的团队(与Portable .NET能相较者倒有之~)。所以,当今最主流的Java跨平台方式,居然是依靠MonoTouch,然后通过IKVM这个.Net扩展插件把Java语言转为Mono能够接受的CIL再进行Mono特有的本地化处理(虽然IKVM对Mono的贡献也不少,但这只优化了Mono,并没有产生Java自己的智能机跨平台项目)。

使用这种方式解决智能机跨平台移植的Java游戏引擎较多,比较有名的是Google支持的PlayN,以及Mario个人主导开发的Libgdx。

MonoTouch+IKVM的最大好处在于,原版Java程序只要经过很少的修改,就可运行于多种智能机平台之上。

PlayN for IOS版部分源码:

Libgdx for IOS 部分源码:

从代码上来说,两者都没对Java代码部分进行什么修改,仅仅以KIVM+MonoTouch提供的IOS本地Java API替换了其原本的Java本地交互部分,就让程序正常跑在IOS环境之上了。

以效果论,这堪称是目前最简洁,最便利的Java智能机平台开发方案。

——假如,MonoTouch不要钱的话。

虽然Mono项目本身是免费的,MonoDevelop这个开发用IDE也是免费的,就连MonoGame这个仿XNA实现都同样是免费的,但关键是——真正有价值的Mono衍生项目MonoTouch却是收费的!而且,此物还是Miguel de Icaza自己搞的,铁了心要收钱,绝对不会开源的商用项目!

上邪!企业版999(完全支持2499)美刀,个人版399美刀,至于free版的MonoTouch呢?除了能在模拟器玩一玩,再没有其他作用。

GameMaker正版授权能跑5大平台,不过299$;Unity3D价格不菲,其3D高质量却摆在眼前。而Xamarin上一个Professional的MonoTouch授权便需399$,这实在让人难以接受。试问又有多少人会花399$(普通企业版999$),只为跑个免费的游戏引擎呢?Xamarin难道不知道,一台iPhone的价格,便足以让某些国家的人缺少肾脏之类的身体重要器官吗?!

而MonoTouch,又是目前以KIVM+Mono方式让Java支持智能机多平台开发的唯一手段。

My God !谁会花几百刀就为用个开源引擎(收费引擎大多还有破解版),谁就真脑子被驴踢了。IKVM这条路,Javaer恐怕是很难走下去了(土豪请自觉退散)。

故此,小弟对Libgdx和PlayN这种开源引擎,采用Mono作为Java跨平台的评价只有四个字。

——浪费时间。

既然Mono这个高富帅靠不住,我们只好退而求其次,找找Java系本身有没有什么和Mono类似,可以把Java源码本地化,却不收费的穷人乐项目存在。

幸运的是,在Java世界中确实有这么一个项目,它,就是传说中的XMLVM。

XMLVM并不是标准的Java实现,它基于Apache Harmony的C/C++实现部分,而非OpenJDK之类。

就原理来说,XMLVM酷似Mono,都是先将原始文件转化为某种中间代码,再将中间代码本地化到指定平台的交叉编译工具。

从适用范围上讲,XMLVM其实比Mono还要广阔,XMLVM可以将任意Java字节码或.NET CIL乃至Ruby翻译成XML文档,再转化为C,Obj-C,Java,C#等等很多种语言输出,这点是Mono所无法比拟的。当然,它最核心,也是最常用的目地, 还是让Java转化为任意语言并本地编译。

通过源自http://xmlvm.org/tutorial/的XMLVM官方描述我们可以看到,就连Oracle一直说要搞定而没有搞定的IOS,也在XMLVM支持之列。

虽然功能上还有所欠缺,不过想把Java转化为C或Ojb-C都可以做到(另,人家注明要抛弃Obj-C了)。

可以说,您何时愿意使用XMLVM,您何时就可以让自己的Java程序跑在IOS系统之上。

——不过XMLVM也是有缺点的。

下面,是一个XMLVM将Java转化为C#时产生的CS文件。

大家可以看到,Java代码确实被转化成了cs文件,而且这个cs文件也确实是可以被编译通过的。但是,为什么语法看上去那么奇怪,好像有N多冗余在其中呢?……

原因就在于,XMLVM对于Java或C#的文件转化并非基于源码,而是基于源码所衍生的Bytecode或CIL指令集。

显然,XMLVM是将比源码更简单的,面向过程的指令集转化到目标源码之上,而非源码对源码的迁移。但这毕竟不是汇编,无论你的初衷怎样,用面向对象的方式,写等价于指令集的代码,都会造成某些一些很不必要的冗余代码。

—— 效率是硬伤。

对于结构复杂的Java代码转化成的C代码,程序性能将会被严重拉低。

——低到和Java原版差别不大的程度(原本的Java代码毕竟是跑虚拟机,这样看来问题不算太大嘛,-_-|||)。

XMLVM发展到2012年,已经可以满足绝大多数Java代码向IOS,Android,WP的迁移。如果能把效率问题更优化一些,减少些转化可能引发的问题,更多地增加本地API。那么,XMLVM超越Mono也指日可待(大部分代码可以转化成功,但非100%能够成功,在使用时也可能出现必须修改Java源码以适应XMLVM的情况存在。比如小弟的LGame整体可以转化,但有个别函数无法生成可用C方法,如果替换写法应该能解决。不过,我还是等XMLVM再成熟点自然解决吧,先搞自己的多平台方案玩……)。

PS:另外还有CodenameOne这种基于XMLVM的二次开发项目。这货不是单纯的衍生,而是重写了部分XMLVM实现替换以自己的类库,而且自带Eclipse和NetBeans可视化插件,做应用的话堪称神物。比较郁闷的是,它重写了一堆JavaME组件,用统一的JavaME API掩盖了本地API,让人看着不爽,做游戏引擎的话,有些东西我想自己改的~

对了,最近类似的项目又新增了Libgdx作者搞的Jake,这是一个J2C的转化工具,一样基于字节码向本地语言的迁移(所以翻译过来的代码看上去也一样奇葩)。

话说Javaer果然都是技术宅,宁愿自己写新的,也不愿意去参加XMLVM项目(>_<|||)。

最后,我们来谈谈前几天横空出世的J2ObjC。

J2ObjC,Google搞的一神物,作用是将Java代码无缝转化为Obj-C代码。

与XMLVM的区别在于,它并不是翻译字节码,而是真的将语法做Java To Obj-C的1:1移植,这样它所生成的.h,.m文件将具有可读性,也方便用户自行改写(Bytecode指令集是面向过程的,而Java源文件的书写方式是面向对象的,有编码习惯在起作用,转化Java指令集比转化Java源码翻译简单的多,因为复杂源码是很难按面向对象翻译准确的)。

比较遗憾的是,Google已明确表示J2ObjC不提供UI界面以及一切与本地API交互的功能,只保证语法的迁移。需要界面之类的,那部分还得自己手写本地代码去(这是在逼人发展J2ObjC的衍生项目啊)。

不过嘛,这对小弟来说已经足够了,因为小弟目前已经在做特定范围内的Java功能再现与自有UI集(就是LGame Java版到其它版本的转换器,话说这货快调完了,Java版API目前已经冻结,正向其它版本迁移)。因为我原先做的已经有J2C#,J2C++加上Google的J2ObjC,彻底省事了……

总之,Java作为智能机领域游戏开发语言,在技术上是绝对可以实现的,前途是光明的。

__________________________

另:

在LGame的SVN中有更新(Beta20120921),目前Java版API已经冻结,只要完整像其它版本的新增类和API迁移就可以发布了(顺便我先重写部分C#版,旧版有部分地方还是坑爹~),并且增加了一些示例源码(如下图所示,两款镇场用的未包括,等正式发布时再加):

 

 

 

4楼mimitracely昨天 23:12沙发~~~3楼baolong47昨天 18:58java大神有新动作了,挺。。。先收起,慢慢看2楼li6185377昨天 13:41鹏大 SVN 地址多少呢?1楼iCOLIN昨天 12:58好文章,学到很多知识!

    
[2] 【RTP】 入门实践小结【精华】
    来源: 互联网  发布时间: 2014-02-18
【RTP】 入门实践总结【精华】
一,windows 下资料
      http://www.cnblogs.com/skyseraph/archive/2012/04/07/2435540.html

一,安装Cmake
二,在 jrtplib-3.9.1_1 中运行 cmake . 生成Makefile
三,然后 make
        接着 make install
        头文件被安装在 /usr/local/include/jrtplib3/ 所以编译程序时候需要添加 -I /usr/local/include/jrtplib3/
        库文件被安装在 /usr/local/lib/libjrtp.a 所以编译程序时候需要添加 -ljrtp
四,编译 example1
        g++ -o test example1.cpp -ljrtp -I /usr/local/include/jrtplib3/

       报错:./test: error while loading shared libraries: libjrtp.so.3.9.1: cannot open shared object file: No such file or directory
       分析:已经将 jrtp 安装完毕,为什么找不到动态库呢?
       解决:将 usr/local/lib/libjrtp.so.3.9.1 拷贝到 usr/lib 下面就可以执行了
五,调试
      报错:The specified port base is not an even number

      分析:jrtp 不支持奇数端口


附:

发送端代码:send.cpp

/*
   Here's a small IPv4 example: it asks for a portbase and a destination and 
   starts sending packets to that destination.
*/

#include "jrtplib3/rtpsession.h"
#include "jrtplib3/rtpudpv4transmitter.h"
#include "jrtplib3/rtpipv4address.h"
#include "jrtplib3/rtpsessionparams.h"
#include "jrtplib3/rtperrors.h"
#ifndef WIN32
	#include <netinet/in.h>
	#include <arpa/inet.h>
#else
	#include <winsock2.h>
#endif // WIN32
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>

using namespace jrtplib;

void checkerror(int rtperr)
{
	if (rtperr < 0) //如果为负数 则返回失败信息
	{
		std::cout << "ERROR: " << RTPGetErrorString(rtperr) << std::endl;
		exit(-1);
	}
}

int main(void)
{
#ifdef WIN32
	WSADATA dat;
	WSAStartup(MAKEWORD(2,2),&dat);
#endif // WIN32
	
	RTPSession sess;
        
	uint16_t portbase=8000,destport=7800;
	uint32_t destip;
	std::string ipstr="127.0.0.1";
	int status,i,num=10;	
	
	destip = inet_addr(ipstr.c_str());//IP地址的建立
	if (destip == INADDR_NONE)
	{
		std::cerr << "Bad IP address specified" << std::endl;
		return -1;
	}
	
	destip = ntohl(destip);
	
	
	RTPUDPv4TransmissionParams transparams;
	RTPSessionParams sessparams;

	sessparams.SetOwnTimestampUnit(1.0/10.0);		
	
	sessparams.SetAcceptOwnPackets(true);
	transparams.SetPortbase(portbase);
        
	status = sess.Create(sessparams,&transparams);	
	checkerror(status);//检查RTP会话创建过程是否失败
	
	RTPIPv4Address addr(destip,destport);//套接字
	
	status = sess.AddDestination(addr);//设置数据发送的目标地址(允许有多个目的地址)
	checkerror(status);
	
	for (i = 1 ; i <= num ; i++)
	{
		printf("\nSending packet %d/%d\n",i,num);
		
		status = sess.SendPacket((void *)"1234567890",10,0,false,10);
		checkerror(status);
		

               // #ifndef RTP_SUPPORT_THREAD
		 //     status = sess.Poll();
		 //     checkerror(status);
              //  #endif // RTP_SUPPORT_THREAD
		
		RTPTime::Wait(RTPTime(1,0));
	}
	
	sess.BYEDestroy(RTPTime(10,0),0,0);

#ifdef WIN32
	WSACleanup();
#endif // WIN32
	return 0;
}
编译:g++ -o send send.cpp  -ljrtp -I /usr/local/include/jrtplib3/


接受端代码:

#include "jrtplib3/rtpsession.h"
#include "jrtplib3/rtpudpv4transmitter.h"
#include "jrtplib3/rtpipv4address.h"
#include "jrtplib3/rtpsessionparams.h"
#include "jrtplib3/rtperrors.h"

#ifndef WIN32
	#include <netinet/in.h>
	#include <arpa/inet.h>
#else
	#include <winsock2.h>
#endif // WIN32

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>

using namespace jrtplib;

// 错误处理函数
void checkerror(int rtperr)
{
	if (rtperr < 0) //如果为负数 则返回失败信息
	{
		std::cout << "ERROR: " << RTPGetErrorString(rtperr) << std::endl;
		exit(-1);
	}
}


int main(int argc, char** argv)
{
     
  RTPSession sess;
  int localport;
  int portbase = 7800;
  int status;

  
  
  // 创建RTP会话
        RTPUDPv4TransmissionParams transparams;
	RTPSessionParams sessparams;
	
	sessparams.SetOwnTimestampUnit(1.0/10.0);		
	
	sessparams.SetAcceptOwnPackets(true);
	transparams.SetPortbase(portbase);
        
	status = sess.Create(sessparams,&transparams);
        checkerror(status);
  
        
        uint32_t destip;
	std::string ipstr="127.0.0.1";
        int destport=7800;
	destip = inet_addr(ipstr.c_str());//IP地址的建立
	if (destip == INADDR_NONE)
	{
		std::cerr << "Bad IP address specified" << std::endl;
		return -1;
	}
	destip = ntohl(destip);
        RTPIPv4Address addr(destip,destport);//套接字
        
        sess.AddToAcceptList(addr);
        
        std::cout<<"Begin receive: \n";
        
        sess.BeginDataAccess();
		
        do{
                  status = sess.Poll();
                  checkerror(status);
           
		if (sess.GotoFirstSourceWithData())
		{        
			do
			{
				RTPPacket *pack;
				
				while ((pack = sess.GetNextPacket()) != NULL)
				{
					// You can examine the data here
					printf("Got packet !\n");
					
					// we don't longer need the packet, so
					// we'll delete it
					sess.DeletePacket(pack);
				}
			} while (sess.GotoNextSourceWithData());
		}
        }
        while(1);
		sess.EndDataAccess();
                
  
  
  return 0;
}
编译:g++ -o receive  receive.cpp  -ljrtp -I /usr/local/include/jrtplib3/




    
[3] Hibernate框架笔记(下)
    来源: 互联网  发布时间: 2014-02-18
Hibernate框架笔记(上)

Hibernate文档笔记共分为二个部分,此处是第一部分,讲述了Contextual Sessions、Configuration、获取SessionFactory和JDBC Connections(Session是对JDBC连接的封装)。

五、Contextual Sessions

许多应用程序需要一种和上下文有关联Hibernate session,这样的session是指贯穿于给定环境的上下文中都有效的session。无论如何,贯穿于应用程序应用上下文由什么组成的清晰度不同,不同的上下文针对当前的概念有不同的范围。

使用Hibernate 3.0以前版本的应用程序,趋于使用自已实现的基于ThreadLocal来维护前后关系的session、诸如HibernateUtil的帮助类;或使用基于代理或拦截机制的第三方的框架(Spring或Pico)。

从Hibernate 3.0.1,Hibernate加入了SessionFactory.getCurrentSession()方法。最初,假定使用JTA事务定义了当前session的scope和context。Hibernate团队维护时,给定了成熟的卓越的JTA TransactionManager的实现方式,多数(但不是所有)应用程序应该使JTA transaction management,不论它是否发布到一个JEE容器中。基于这一点,基于用JTA来维护上下文关系中的session应该是必须的。

无论如何,在Hibernate 3.1,SessionFactory.getCurrentSession()之后的处理,是可以被插拔的,也就是说可以session的范围和上下文。新扩展接口(org.hibernate.context.CurrentSessionContext)和新的配置参数(hibernate.current_session_context_class)被加入,允许插拔,也就是说可以定义session的范围和上下文。

细节可以查看org.hibernate.context.CurrentSessionContext的文档。它定义了一个currentSession()方法,负责跟踪与当前上下文相关联的session。Hibernate提供了这个接口的三种实现方式。

1.org.hibernate.context.JTASessionContext

当前session,通过JTA事务跟踪和标识生命周期。这里的处理过程在处理方法上和老JTA是相似的。

2.org.hibernate.context.ThreadLocalSessionContext

当前session,通过当前执行的线程来跟踪。

3.org.hibernate.context.ManagedSessionContext

当前session,通过当前执行的线程来跟踪。你是负责绑定和解除当前session到执行线程通过使用这个类的静态方法。该类不会open、flush、close session。

前两个实现类,提供了“一个session对应一个数据库事务”的编程模式,也就是众所周知的“session-per-request”模式。Hibernate session的开始和结束,是以数据库中事务的执行时间为依据的。如果你使用编程方式划分事务,用简单的JSE需不是JTA,你应该考虑使用Hibernate事务APIs来隐藏低层的事务代码。如果你使用的是JTA,使用JTA的接口来划分事务。如果你在一个支持CMT(Container Management Transaction)的容器运行程序,事务是通过声明定义,在你程序中不需要任何的代码来划分事务。

Hibernate.current_session_context_class参数应该指定,一个org.hibernate.context.CurrentSessionContext的实现类。如果配置参数没有被设置,而是配置了一个org.hibernate.transaction.TransactionManagerLookup被设置,Hibernate将使用org.hibernate.context.JTASessionContext,这里要考虑向后兼容。典型的情况下,这个参数是使用的类的名字。对于Hibernate提供的三个实现类,有对应的三个简短名,“jta”、“thread”、“managed”。

六、Configuration

1.编程配置

一个org.hibernate.cfg.Configuration的实例表示一个应用程序的所有Java类型到数据库类型的映射。org.hibernate.cfg.Configuration是用来建造一个org.hibernate.SessionFactory。被编译的映射是来自所有的XML映射文件。

片断1.

  • Configuration cfg = new Configuration().addResource(“test.hbm.xml”);
  • 片断2.

  • Configuration cfg = new Configuration().addClass(com.test.class);
  • 片断3.

  • Configuration cfg = new Configuration().setProperty(“hibernate.dialect”, “org.hibernate.dialect.DB2Dialect”);
  • Configuration可以接收的选项:

    (1)传递一个java.util.Properties到Configuration.setProperties()。

    (2)放一个hibernate.properties文件到类路径的根目录。

    (3)设置系统properties,通过java –Dproperty=value。

    (4)包含标签指定值在hibernate.cfg.xml文件。

    org.hibernate.cfg.Configuration对象是有意作为一个开始时间生成的对象的,一旦SessionFactory被创建,他将被抛弃掉。

    七、获取SessionFactory

    当org.hibernate.cfg.Configuration解析完所有的映射文件后,应用程序应该获取一个org.hibernate.Session实例的工厂。这个工厂是被应用程序的所有线程共享的。

  • SessionFactory sessionFactory = cfg.buildSessionFactory();
  • Hibernate允许应用程序实例多个SessionFactory。对于使用多个数据库的应用程序是非常有用的。

    八、JDBC Connections(Session是对JDBC连接的封装)

    通常,你应该使用org.hibernate.SessionFactory来创建或共享JDBC。如果这采用这种方法,是非常简单的。

  • Session session = sessionFactory.openSession();
  • 当你的操作需要访问数据库时,一个JDBC连接就会从连接池中被获取。

    对于这个工作,我们应该给Hibernate提供一些JDBC连接属性。所有的Hibernate属性名和语义学都被定义在org.hibernate.cfg.Environment。我们现在描述对于JDBC连接配置的一些更重要的设置。

    1.如果你设置以下属性,Hibernate将获取或共享连接使用java.sql.DriverManager:

  • hibernate.connection.driver_class
  • hibernate.connection.url
  • hibernate.connection.username
  • hibernate.connection.password
  • hibernate.connection.pool_size
  • Hibernate自己拥有的连接池算法是没有发展的。他是为了你的初始接触使用的,而不是为了你的产品使用的,甚至性能测试时使用。为了更好的性能和稳定性考虑,你应该使用第三方的连接池产品。只需要替换hibernate.connection.pool_size属性的设置用相应连接池的设置。这将关闭Hibernate内部的连接池。例如,可以使用C3P0。

    C3P0是一个开源的JDBC连接池,被放置在Hibernate发布文件的lib目录下,随Hibernate一块发行。如果你设置hibernate.c3p0.*属性,Hibernate将会使用org.hibernate.connection.C3P0ConnectionProvider为共享连接。如果你想使用proxool作为连接池,你可以通过查阅hibernat.properties或Hibernate站点获取需要设置的属性名设置。

    C3P0配置举例,属性文件片断:

  • hibernate.connection.driver_alt">hibernate.connection.url=
  • hibernate.connection.username=
  • hibernate.connection.password=
  • hibernate.c3p0.min_size=
  • hibernate.c3p0.max_size=
  • hibernate.c3p0.timeout=
  • hibernate.c3p0.max_statements=
  • hibernate.dialect=
  • 2.对于在应用服务器内运行的程序,多数情况你应该配置Hibernate通过JNDI找到服务器的javax.sql.DataSource来获取连接。你需要设置以下属性。

  • hibernate.connection.datasource
  • hibernate.jndi.url (可选)
  • hibernate.jndi.class (可选)
  • hibernate.connection.username (可选)
  • hibernate.connection.password (可选)
  • 你可以通过实现org.hibernate.connection.ConnectionProvider来定义自己的获得连接的策略。通过hibernate.connection.provider_class配置使用自己的定义起作用。


        
    最新技术文章:
    ▪Android开发之登录验证实例教程
    ▪Android开发之注册登录方法示例
    ▪Android获取手机SIM卡运营商信息的方法
    ▪Android实现将已发送的短信写入短信数据库的...
    ▪Android发送短信功能代码
    ▪Android根据电话号码获得联系人头像实例代码
    ▪Android中GPS定位的用法实例
    ▪Android实现退出时关闭所有Activity的方法
    ▪Android实现文件的分割和组装
    ▪Android录音应用实例教程
    ▪Android双击返回键退出程序的实现方法
    ▪Android实现侦听电池状态显示、电量及充电动...
    ▪Android获取当前已连接的wifi信号强度的方法
    ▪Android实现动态显示或隐藏密码输入框的内容
    ▪根据USER-AGENT判断手机类型并跳转到相应的app...
    ▪Android Touch事件分发过程详解
    ▪Android中实现为TextView添加多个可点击的文本
    ▪Android程序设计之AIDL实例详解
    ▪Android显式启动与隐式启动Activity的区别介绍
    ▪Android按钮单击事件的四种常用写法总结
    ▪Android消息处理机制Looper和Handler详解
    ▪Android实现Back功能代码片段总结
    ▪Android实用的代码片段 常用代码总结
    ▪Android实现弹出键盘的方法
    ▪Android中通过view方式获取当前Activity的屏幕截...
    ▪Android提高之自定义Menu(TabMenu)实现方法
    ▪Android提高之多方向抽屉实现方法
    ▪Android提高之MediaPlayer播放网络音频的实现方法...
    ▪Android提高之MediaPlayer播放网络视频的实现方法...
    ▪Android提高之手游转电视游戏的模拟操控
     


    站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3