pwlib是一套跨平台的C++的开发库,使基于pwlib上开发的应用能够很少量的移植就可以跑
在windows和unix的平台上.
Open323是澳洲的一家公司驱动的open source的h323协议族实现, 还不够十分的完整, 但
是已经是非常的难得了.
在windows上和linux下都能编译使用, 我已经试过了. Windows上编译他们比较麻烦, 注意
的是一定要用batch building. 在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:
# Simple makefile for the hello world program PROG = hello
SOURCES = hello.cxx ifndef PWLIBDIR
PWLIBDIR=$(HOME)/pwlib endif
include $(PWLIBDIR)/make/ptlib.mak 关键是包含了一个ptlib.mak hello.cxx #include
class Hello : public PProcess {
PCLASSINFO(Hello, PProcess) public:
void Main(); };
PCREATE_PROCESS(Hello) void Hello::Main() {
cout << \}
非常有代表性. Include $(PWLIBDIR)/make/ptlib.mak 这样就可以make all, make debu
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, 应会议的需要而产生, 信令相关的东西用H225 H245,类似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中称之为Interface thread. 程序注解: main.h
这个文件包含了程序用到的所有类的声明, 一般应该至少有三个类:
来自PProcess的一个主进程的, 或者说作为界面线程的;(只有一个对象) 来自H323Endpoint的, 标识这个H323端点的;(只有一个对象)
来自H323Connection的, 标识所有和这个H323端点相关的连接;(可以有多个) #ifndef _SimpleH323_MAIN_H #define _SimpleH323_MAIN_H //避免头文件重复包含 #include
class SimpleH323EndPoint : public H323EndPoint {
//使用Pwlib的要求, 就像使用MFC, 有n多的宏, 可以看看pwlib的源码, //宏展开都干了什么
PCLASSINFO(SimpleH323EndPoint, H323EndPoint); public:
SimpleH323EndPoint(); ~SimpleH323EndPoint();
// overrides from H323EndPoint // 重载H323EndPoint的函数
// 当收到一个远程的呼入和发出呼出的请求的时候
virtual H323Connection * CreateConnection(unsigned callReference); // 有远程的请求来到, 这是在CreateConnection之后的
virtual BOOL OnIncomingCall(H323Connection &, const H323SignalPDU &, H323Signa lPDU &);
//应答远程的呼入 virtual H323Connection::AnswerCallResponse OnAnswerCall(H323Connection &, cons
t PString &, const H323SignalPDU &, H323SignalPDU &);
//当连接被Forward
virtual BOOL OnConnectionForwarded(H323Connection &, const PString &, const H3
23SignalPDU &); //当连接建立
virtual void OnConnectionEstablished(H323Connection & connection, const PStrin
g & token); //当连接撤销
virtual void OnConnectionCleared(H323Connection & connection, const PString &
clearedCallToken);
//当连接需要打开声音的通道
virtual BOOL OpenAudioChannel(H323Connection &, BOOL, unsigned, H323AudioCodec &);
// New functions
// 自己添加的新函数, 父类中不存在 BOOL Initialise(PArgList &); BOOL SetSoundDevice(PArgList &, const char *, PSoundChannel::Directions); // 每个连接会有一个Token来唯一标识 PString currentCallToken; protected:
BOOL autoAnswer;
PString busyForwardParty; };
class SimpleH323Connection : public H323Connection {
PCLASSINFO(SimpleH323Connection, H323Connection);
public:
//创建连接对象的时候将Endpoint的对象以引用传进来
//引用的概念就是将整个对象暴露给你的意思, 不是复制了一份的意思,
//对象还是原来的对象, 所以在Connection中修改了EndPoint的某些属性后 //就是在操作着传进来的对象, 这是C++的基本概念, OpenH323大量的使用 //引用传递对象, 对引用的概念要理解
SimpleH323Connection(SimpleH323EndPoint &, unsigned); //重载了两个父类的函数
// 当打开逻辑通道的时候(等于没说)
virtual BOOL OnStartLogicalChannel(H323Channel &);
// 处理用户输入, 这个不是之运行这个程序的用户,而是这个连接上的用户输入
// 一般应该是拨号了之类的,
virtual void OnUserInputString(const PString &); protected: // 快速连接?? BOOL noFastStart; };
class SimpleH323Process : public PProcess {
//主进程, 类似VC的用户界面线程, //他是整个程序的入口点, 和结束点
//创建了EndPoint对象后会有好几个线程启动 //这个就是主线程
PCLASSINFO(SimpleH323Process, PProcess) public:
SimpleH323Process(); ~SimpleH323Process();
//这个函数会被自动调用, 是我们程序的入口了 void Main(); protected:
//这个H323端点对象
SimpleH323EndPoint * endpoint; };
#endif // _SimpleH323_MAIN_H 下面是main.cpp 所有的类的实现了 #include