使用openh323开发学习资料.docx

上传人:b****9 文档编号:25610561 上传时间:2023-06-10 格式:DOCX 页数:65 大小:35.72KB
下载 相关 举报
使用openh323开发学习资料.docx_第1页
第1页 / 共65页
使用openh323开发学习资料.docx_第2页
第2页 / 共65页
使用openh323开发学习资料.docx_第3页
第3页 / 共65页
使用openh323开发学习资料.docx_第4页
第4页 / 共65页
使用openh323开发学习资料.docx_第5页
第5页 / 共65页
点击查看更多>>
下载资源
资源描述

使用openh323开发学习资料.docx

《使用openh323开发学习资料.docx》由会员分享,可在线阅读,更多相关《使用openh323开发学习资料.docx(65页珍藏版)》请在冰豆网上搜索。

使用openh323开发学习资料.docx

使用openh323开发学习资料

 

使用openh323开发

pwlib是一套跨平台的C++的开发库,使基于pwlib上开发的应用能够很少量的移植就可以跑

在windows和unix的平台上.

Open323是澳洲的一家公司驱动的opensource的h323协议族实现,还不够十分的完整,但

是已经是非常的难得了.

在windows上和linux下都能编译使用,我已经试过了.Windows上编译他们比较麻烦,注意

的是一定要用batchbuilding.在VC7上编译openh323的动态连接库的时候,VS.net会崩溃

注意避开,不过也可以试试看看现象,如果能够解决,请告诉我一下.

在linux上编译就没有什么好说的了,设好两个环境变量(PWLIBDIR,OPENH323DIR),就可

以在展开的目录下编译了,先编译PWLIB,再编译OPENH323,别忘了将相应xx/lib写到/et

c/ld.so.conf下.我这里可能对安装讲的不够详细,openh323讲的非常详细,大家可以去

看.

以linux平台为例:

使用pwlib,在成功编译之后,到$(PWLIBDIR)/SAMPLES/

这里是一些例子,hello_world是个非常简单的工程,从这里我们可以看到如何写使用pw

lib的Makefile:

#Simplemakefileforthehelloworldprogram

PROG=hello

SOURCES=hello.cxx

ifndefPWLIBDIR

PWLIBDIR=$(HOME)/pwlib

endif

include$(PWLIBDIR)/make/ptlib.mak

关键是包含了一个ptlib.mak

hello.cxx

#include

classHello:

publicPProcess

{

PCLASSINFO(Hello,PProcess)

public:

voidMain();

};

PCREATE_PROCESS(Hello)

voidHello:

:

Main()

{

cout<<"Helloworld!

\n";

}

非常有代表性.Include$(PWLIBDIR)/make/ptlib.mak这样就可以makeall,makedebu

g的之类的进行编译,需要的头文件库都会替你安排好.编译的结果就会放在obj_linux_x

86_xx,xx表示你用的是debug编译还是其他,如果是debug,xx就是d.

使用pwlib的程序,必然要有一个PProcess的子类,作为整个进程,这是指在console模式

下,gui模式的用PApplication这个我没有用过.Pwlib里面的类大多都是P开头,(可能是

取其兼容的意思,跨平台的特性,我瞎猜的),在进程中如果想创建新的线程就创建PThre

ad子类的对象,对于这种关于过程的类,都有Main函数等待子类去实现.

在使用所有的P类的时候,注意使用两个宏,声明类的时候PCLASSINFO(Hello,PProcess)

;分号可以加,也可不加.PProcess的子类的实现的时候要用PCREATE_PROCESS(Hello);,

 这个东西把main()之类的系统入口封装了,由他来调用Main()成员函数.在使用线程的时

候,如果想让线程从线程的对象一创建就运行,就应该在PThread子类中的构造函数中调用

父类的Resume().关于pwlib先说这些,在使用Openh323的时候到处都会用到pwlib的东西

和概念.

Openh323:

终于进入正题了,先粗略的讲点概念(多余了),H323是指协议族了,包含了很多规范,它

来自ITU,应会议的需要而产生,信令相关的东西用H225H245,类似Q931,用ASN1编码后在

tcp之上传输,数据相关的就是编码解码的东西了(包括音频视频),音频g711(alaw,ulaw

)了等等多了,视频h261,好像h263还没实现.

在H323的系统里进行通讯的角色实体就是Endpoint,每个Endpoint可以有很多的Connecti

on,每个Endpoint也可以拥有很多的逻辑角色,这个不讨论.

Endpoint在Openh323中就是类H323Endpoint的实例

Connection在Openh323中就是H323Connection的实例

当Endpoint接收了一个远程的连接请求,Endpoint就会创建一个H323Connection;

当Endpoint发出一个连接的请求,Endpoint也会创建一个H323Connection

Connection就会进入一个状态机,在各个状态中,Connetcion会相应的执行相应的方法,

 这些方法,大多都是Onxxxxx(),是虚函数,我们可以自己通过继承H323Connection创建

其子类,并且在我们想做事的时机去重载相应的虚函数.这是使用Openh323的一个基本的

思路.

现在我们可以看看如何写一个自己H323的Endpoint,让它能够和netmeeting互操作.成功编

译Openh323后在它的samples的目录下面有几个例子,mfc是指在windows下如何使用MFC和

Openh323一起开发,还有simple,这是个简单的H323的Endpoint的实现,作为理解OpenH3

23的库如何使用和开发的技巧方法已经足够了.

程序运行主线:

PWLIB(PCREATE_PROCESS(SimpleH323Process))--SimpleH323Process:

:

SimpleH

323Process()--SimpleH323Process:

:

Main();

Main()如果结束,这个程序就结束了,可是Main()里面有个死循环,写过图形程序的朋友

们都知道,这就是在等消息来呀.在VC中称之为Interfacethread.

程序注解:

main.h

这个文件包含了程序用到的所有类的声明,一般应该至少有三个类:

来自PProcess的一个主进程的,或者说作为界面线程的;(只有一个对象)

来自H323Endpoint的,标识这个H323端点的;(只有一个对象)

来自H323Connection的,标识所有和这个H323端点相关的连接;(可以有多个)

#ifndef_SimpleH323_MAIN_H

#define_SimpleH323_MAIN_H

//避免头文件重复包含

#include

classSimpleH323EndPoint:

publicH323EndPoint

{

//使用Pwlib的要求,就像使用MFC,有n多的宏,可以看看pwlib的源码,

//宏展开都干了什么

PCLASSINFO(SimpleH323EndPoint,H323EndPoint);

public:

SimpleH323EndPoint();

~SimpleH323EndPoint();

//overridesfromH323EndPoint

//重载H323EndPoint的函数

//当收到一个远程的呼入和发出呼出的请求的时候

virtualH323Connection*CreateConnection(unsignedcallReference);

//有远程的请求来到,这是在CreateConnection之后的

virtualBOOLOnIncomingCall(H323Connection&,constH323SignalPDU&,H323Signa

lPDU&);

//应答远程的呼入

virtualH323Connection:

:

AnswerCallResponseOnAnswerCall(H323Connection&,cons

tPString&,constH323SignalPDU&,H323SignalPDU

&);

//当连接被Forward

virtualBOOLOnConnectionForwarded(H323Connection&,constPString&,constH3

23SignalPDU&);

//当连接建立

virtualvoidOnConnectionEstablished(H323Connection&connection,constPStrin

g&token);

//当连接撤销

virtualvoidOnConnectionCleared(H323Connection&connection,constPString&

clearedCallToken);

//当连接需要打开声音的通道

virtualBOOLOpenAudioChannel(H323Connection&,BOOL,unsigned,H323AudioCodec

 &);

//Newfunctions

//自己添加的新函数,父类中不存在

BOOLInitialise(PArgList&);

BOOLSetSoundDevice(PArgList&,constchar*,PSoundChannel:

:

Directions);

//每个连接会有一个Token来唯一标识

PStringcurrentCallToken;

protected:

BOOLautoAnswer;

PStringbusyForwardParty;

};

classSimpleH323Connection:

publicH323Connection

{

PCLASSINFO(SimpleH323Connection,H323Connection);

public:

//创建连接对象的时候将Endpoint的对象以引用传进来

//引用的概念就是将整个对象暴露给你的意思,不是复制了一份的意思,

//对象还是原来的对象,所以在Connection中修改了EndPoint的某些属性后

//就是在操作着传进来的对象,这是C++的基本概念,OpenH323大量的使用

//引用传递对象,对引用的概念要理解

SimpleH323Connection(SimpleH323EndPoint&,unsigned);

//重载了两个父类的函数

//当打开逻辑通道的时候(等于没说)

virtualBOOLOnStartLogicalChannel(H323Channel&);

//处理用户输入,这个不是之运行这个程序的用户,而是这个连接上的用户输入

//一般应该是拨号了之类的,

virtualvoidOnUserInputString(constPString&);

protected:

//快速连接?

?

BOOLnoFastStart;

};

classSimpleH323Process:

publicPProcess

{

//主进程,类似VC的用户界面线程,

//他是整个程序的入口点,和结束点

//创建了EndPoint对象后会有好几个线程启动

//这个就是主线程

PCLASSINFO(SimpleH323Process,PProcess)

public:

SimpleH323Process();

~SimpleH323Process();

//这个函数会被自动调用,是我们程序的入口了

voidMain();

protected:

//这个H323端点对象

SimpleH323EndPoint*endpoint;

};

#endif//_SimpleH323_MAIN_H

下面是main.cpp所有的类的实现了

#include

#ifdef__GNUC__

#defineH323_STATIC_LIB

#endif

#include"main.h"

#include"../../version.h"

#definenewPNEW

//这个东西里边可能封装了标准的main函数

PCREATE_PROCESS(SimpleH323Process);

///////////////////////////////////////////////////////////////

//几个宏都在version.h里面定义

SimpleH323Process:

:

SimpleH323Process()

:

PProcess("OpenH323Project","SimpleH323",

MAJOR_VERSION,MINOR_VERSION,BUILD_TYPE,BUILD_NUMBER)

{

endpoint=NULL;

}

SimpleH323Process:

:

~SimpleH323Process()

{

deleteendpoint;

}

voidSimpleH323Process:

:

Main()

{

cout<

<<"Version"<

<<"by"<

<<"on"<

<<"("<

//Getandparseallofthecommandlinearguments.

//分析命令行参数,略去数行

PArgList&args=GetArguments();

args.Parse(

"a-auto-answer."

"b-bandwidth:

"

"B-forward-busy:

"

"D-disable:

”FALSE);

if(args.HasOption(h)||(!

args.HasOption(l)&&args.GetCount()==0)){

//如果没有参数或者参数是h,就输出如何使用,此处略去数行

}

//这个东西暂时不管

#ifPTRACING

#endif

//CreatetheH.323endpointandinitialiseit

//H323EndPoint创建了,并且把命令参数传过去初始化,初始化的时候做了一些事

endpoint=newSimpleH323EndPoint;

if(!

endpoint->Initialise(args))

return;

//看看命令行里是不是想直接呼叫另一个H323的endpoint.有没有l(listen)的option

//如果是就MakeCall,

//Seeifmakingacallorjustlistening.

if(args.HasOption(l))

cout<<"Waitingforincomingcallsfor\""<GetLocalUserName()<<

 "\"\n";

else{

cout<<"Initiatingcallto\""<

endpoint->MakeCall(args[0],endpoint->currentCallToken);

}

cout<<"PressXtoexit."<

//Simplestpossibleuserinterface

//简单的用户界面,会有一个提示>

//取pid是我加的

for(;;){

pid_tthispid;

charprom[20];

thispid=getpid();

sprintf(prom,"H323%d>",thispid);

cout<

PCaselessStringcmd;

cin>>cmd;

if(cmd=="X")

break;

if(cmd.FindOneOf("HYN")!

=P_MAX_INDEX){

H323Connection*connection;

//使用lock就是怕别的线程把它给删了

//因为这里正用着呢

connection=endpoint->FindConnectionWithLock(endpoint->currentCallToken);

if(connection!

=NULL){

if(cmd=="H")

connection->ClearCall();

elseif(cmd=="Y")

connection->AnsweringCall(H323Connection:

:

AnswerCallNow);

elseif(cmd=="N")

connection->AnsweringCall(H323Connection:

:

AnswerCallDenied);

connection->Unlock();

}

}

}

cout<<"Exiting"<

}

//Main函数结束

//自己的Init函数

BOOLSimpleH323EndPoint:

:

Initialise(PArgList&args)

{

//Getlocalusername,multipleusesof-uindicatesadditionalaliases

if(args.HasOption(u)){

PStringArrayaliases=args.GetOptionString(u).Lines();

//设定改Endpoint的username

SetLocalUserName(aliases[0]);

//设定Aliases就是每个Endpoint可以有好多名字的意思

for(PINDEXi=1;i

AddAliasName(aliases[i]);

}

//Setthevariousoptions

//设置静音检测否

SetSilenceDetectionMode(args.HasOption(e)?

H323AudioCodec:

:

NoSilenceDetection

 

:

H323AudioCodec:

:

AdaptiveSilenceDetection);

//快速连接?

DisableFastStart(args.HasOption(f));

//H245通道

DisableH245Tunneling(args.HasOption(T));

autoAnswer=args.HasOption(a);

busyForwardParty=args.GetOptionString(B);

if(args.HasOption()){

initialBandwidth=args.GetOptionString().AsUnsigned()*100;

if(initialBandwidth==0){

cerr<<"Illegalbandwidthspecified."<

returnFALSE;

}

}

if(args.HasOption(j)){

unsignedjitter=args.GetOptionString(j).AsUnsigned();

//设定音频抖动的,应该影响到接收的缓存

if(jitter>=20&&jitter<=10000)

SetMaxAudioDelayJitter(jitter);

else{

cerr<<"Jittershouldbebetween20millisecondsand10seconds."<

returnFALSE;

}

}

//设定声音设备

//也可以不用声音设备,比如Openh323工程的子项目OpenAM和OpenMCU

//都使演示了如何不使用声音物理设备的方法,我想那里边的东西会对某些朋友们

//的需求比较合适

if(!

SetSoundDevice(args,"sound",PSoundChannel:

:

Recorder))

returnFALSE;

if(!

SetSoundDevice(args,"sound",PSoundChannel:

:

Player))

returnFALSE;

if(!

SetSoundDevice(args,"sound-in",PSoundChannel:

:

Recorder))

returnFALSE;

if(!

SetSoundDevice(args,"sound-out",PSoundChannel:

:

Player))

returnFALSE;

//设定decodeencode的能力

//H323EndPoint在真正进行数据通讯之前要进行能力的交换,说明自己能够接收和发送

什么标准的数据,g.711是必须支持的.

//Setthedefaultcodecsavailableonsoundcards.

AddAllCapabilities(0,0,"GSM*{sw}");

AddAllCapabilities(0,0,"G.711*{sw}");

AddAllCapabilities(0,0,"LPC*{sw}");

AddAllUserInputCapabilities(0,1);

RemoveCapabilities(args.GetOptionString(D).Lines());

ReorderCapabilities(args.GetOptionString(P).Lines());

cout<<"Localusername:

"<

<<"Silenceco

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 自然科学 > 物理

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1