用NetMeeting开发网络会议软件
北京航空航天大学图像中心 赵 宇
一、 NetMeeting概述
Microsoft NetMeeting是微软家族中的一个网络通信服务产品。有了 NetMeeting,您可以参加网络会议、进行协同工作以及通过Internet或企业Intranet共享信息。
NetMeeting的基本原理是:在两个IP之间建立起语音、视频和数字会议,获得一个丰富多彩的实时协作环境。双方或者多方可以交换文件,在白板上交流思想,进行讨论或者共享应用程序和桌面。
NetMeeting支持ITU的H.323标准和T.120标准,以及IETF 的LDAP目录服务标准,有关这些标准的细节请参考相关资料。在Windows 98第一版中捆绑了NetMeeting 2.0,在Windows 98第二版和Windows 2000中捆绑了NetMeeting 3.0。 NetMeeting本身是基于Microsoft COM技术设计的,它提供了一整套接口函数,使我们可以在NetMeeting的基础上进行二次开发。有了NetMeeting,我们可以跳过网络通信的底层技术细节,集中精力在软件的功能设计上,开发出满足自己需求的网络通信产品。微软的很多产品都具有二次开发的能力,这要归功于COM的威力,它可以在二进制级进行代码重用,为现代软件的开发带来了极大的革新。
如果你使用的是中文版Windows 98或者Windows 2000,建议您到微软的主页上去下载英文版的NetMeeting 3.0,因为中文版的NetMeeting 在传输中文名字的文件时会产生乱码(这个现象好奇怪)。NetMeeting的网址是 www.microsoft.com/netmeeting,在这里您还可以下载NetMeeting的SDK包,其中包括详细的文档和一些示例程序。
图1描述了NetMeeting的软件结构。从图中可以看到,我们只要通过调用NetMeeting的COM API函数,就可以管理一个网络会议,完成所有 NetMeeting的功能,而大量的底层技术细节都由NetMeeting自己处理了。
NetMeeting SDK包括一个ActiveX控件和一组COM对象。其中的ActiveX控件只能实现很简单的功能,可以在Web页面上使用。如果想开发比较复杂的网络会议软件,还需要直接调用其COM API。NetMeeting的COM模型如图2所示。
每个COM对象都有不少接口函数,几乎每个对象都有一个相应的Notification对象,我们可以通过它在运行时刻获得COM对象的事件。只要按照一定的规范使用这些COM对象,就可以创建一个与NetMeeting完全一样的网络会议软件。
用于COM技术比较复杂,直接调用COM API还是非常麻烦的,所以我在NetMeeting COM API的基础上用C++语言编写了一个类TConf。它把一些COM调用的细节封装起来,使得创建一个网络会议变得更加简单、方便。
TConf是一个包括语音通道、数据传输和文件传输的网络会议类,视频和应用程序共享并没有包含在内。下面是TConf的头文件,其中没有包括 Private成员:
class TConf
{
public:
TConf(HWND);
~TConf();
HRESULT Initialize();
HRESULT Uninitialize();
HRESULT Call(BSTR);
HRESULT HangUp();
BOOL InConnection();
HRESULT RejectCall();
HRESULT AcceptCall();
HRESULT HookDataChannel();
HRESULT HookFtChannel();
HRESULT SendData(ULONG uSize, BYTE *pvBuffer);
virtual HRESULT CallCreated(INmCall *pCall);
virtual HRESULT ConferenceActive();
virtual HRESULT ConferenceCreated(INmConference *);
virtual HRESULT ConferenceIdle();
virtual HRESULT MemberAdded(INmMember *pMember);
virtual HRESULT MemberRemoved(INmMember *pMember);
virtual HRESULT MemberUpdated(INmMember *pMember);
virtual HRESULT DataSent(INmMember *pMember,
ULONG uSize, LPBYTE pb);
virtual HRESULT DataReceived(INmMember
*pMember, ULONG uSize, LPBYTE pb);
virtual HRESULT CallRing();
virtual HRESULT CallRejected();
virtual HRESULT CallAccepted();
virtual HRESULT FtUpdate(CONFN uNotify, INmFt * pFt);
HRESULT FtSendFile(BSTR);
HRESULT SetReceiveFileDir(BSTR bstrDir);
HRESULT GetReceiveFileDir(BSTR *pbstrDir);
};
使用TConf时,应先把必要的文件包含入C++工程,再从TConf派生子类,重新定义其中的虚函数,以完成定制的功能。TConf的代码比较长,这里只简要介绍一下:
看到上面TConf的定义后,大家可能就跃跃欲试要编写自己的网络会议软件了,下面用一个C++ Builder的例子来演示TConf的用法。
首先创建一个窗体,其中包括一个Edit1组件,用于输入呼叫的地址;Memo1组件用于显示双方Chart的内容;Edit2组件用于输入自己的发言,按“回车”键后会发送其内容;Button2用于选择一个文件并发送给对方。TConf的派生类TMyConf重新定义了DataSent函数和DataReceived函数,用于在Memo1中显示发送的数据。语音通道一直打开,双方可以通过麦克风进行交谈。该示例程序的界面如图3所示。
TForm1 *Form1;
class TMyConf : public TConf
{
public:
TMyConf(HWND);
~TMyConf();
virtual HRESULT DataSent(INmMember
*pMember, ULONG uSize, LPBYTE pb);
virtual HRESULT DataReceived(INmMember
*pMember, ULONG uSize, LPBYTE pb);
};
HRESULT TMyConf::DataSent(INmMember
*pMember, ULONG uSize, LPBYTE pb)
{
return DataReceived(m_pINmMember,uSize,pb);
}
HRESULT TMyConf::DataReceived(INmMember
*pMember, ULONG uSize, LPBYTE pb)
{
WideString User;
if (pMember)
{
pMember->GetName(&User);
}
else
{
User=“";
}
Form1->Memo1->Lines->Add(AnsiString
(User)+“:"+AnsiString((LPTSTR)pb));
return S_OK;
}
void __fastcall TForm1::FormCreate(TObject *Sender)
{
MyConf = new TMyConf(Handle);
MyConf->Initialize();
}
void __fastcall TForm1::FormClose(TObject
*Sender, TCloseAction &Action)
{
delete MyConf;
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
MyConf->Call((WideString)Edit1->Text);
}
void __fastcall TForm1::Button2Click(TObject *Sender)
{
if (OpenDialog1->Execute())
{
MyConf->FtSendFile((WideString)OpenDialog1->FileName);
}
}
void __fastcall TForm1::Edit2KeyPress
(TObject *Sender, char &Key)
{
if (Key==13)
{
MyConf->SendData(Edit2->Text.Length() + 1,
(BYTE*)Edit2->Text.c_str());
}
}
怎么样,只短短几行代码,一个网络会议就有个初步的模样了。由于NetMeeting是在两个IP地址之间的通信连接,所以进行网络会议时一定要使用TCP/IP协议。我们可以使用局域网连接,或者通过RAS进行连接。如果要通过因特网进行连接,则需要知道网络会议各方的IP地址。在这种情况下,可以使用Microsoft ILS 服务器,或者通过FTP、Email等方式把自己的IP地址告知对方。