1、服务器环境
服务器是在xp系统下安装的(我是在虚拟机中的xp系统下安装的),服务器采用的是Openfire 3.9.3版本,安装服务器时采用的是服务器自带的数据库。
2、编程环境
编程环境是在win7 64位系统下进行的,采用的是Microsoft Visual Studio 2010 旗舰版进行编程。
3、客户端编程采用的技术
3.1采用基于C++实现的XMPP协议客户端开源库gloox
gloox简介:
gloox是一个开源的跨平台的C++实现的XMPP协议开发包,目前的版本为1.0.10测试版。
XMPP协议只是一个协议,一个约定,但本身并没有提供实现方式。也就是说,XMPP定义的那些关键字以及发送消息这些是需要实现的,只要按照XMPP协议来做的话,就可以互通消息了。而gloox就是实现这样一个协议的开发包,我们可以通过这个开发包,开发自己的应用来。
那么gloox如何实现了XMPP协议的呢,其实它的底层就是一个socket在收发数据,然后将数据进行XML解析,封装就可以了。
我采用的是gloox 0.9.9.12版本,可以在这里下载点击打开链接。
在Microsoft Visual Studio 2010 旗舰版下编译生成了相应的动态库。
3.2下面介绍下如何把gloox中的源代码加入到工程中去:
自己新建一个工程,然后在工程中新建一个文件夹,我这里叫src,然后将gloox0.9.9.12 文件夹下的src文件夹中的除tests、example等文件夹外所有的文件拷贝到这里新建的src文件夹下。然后将先前编译生成的gloox.lib和gloox.dll文件拷贝到工程下。
我这里新建的个是一个win32控制台应用程序,应用程序类型为DLL的工程,目的是为了将所有对XMPP通信的操作都在该动态库中完成,与对窗口的操作进行分开。
下面开始为该工程添加文件,完成即时通信中的用户注册、登录、修改密码、修改个人资料,显示好友列表、添加联系人、聊天信息的发送和接收、创建聊天室、传送文件、视频等功能。
用户注册
-
#include "./src/client.h"
-
#include "./src/connectionlistener.h" -
#include "./src/registration.h" -
#include "./src/logsink.h" -
#include "./src/loghandler.h" -
using namespace gloox; -
#include -
#include "afxmt.h" -
class RegTest : public RegistrationHandler, ConnectionListener, LogHandler -
{ -
public: -
RegTest(bool ischangePassword) ; -
virtual ~RegTest(); -
void start(CString serverName,CString userName,CString pwd); -
virtual void onConnect(); -
virtual void onDisconnect( ConnectionError e ); -
virtual bool onTLSConnect( const CertInfo& info ); -
virtual void handleRegistrationFields( const JID& /*from*/, int fields, std::string instructions ); -
virtual void handleRegistrationResult( const JID& /*from*/, RegistrationResult result ); -
virtual void handleAlreadyRegistered( const JID& /*from*/ ); -
virtual void handleDataForm( const JID& /*from*/, const DataForm& /*form*/ ); -
virtual void handleOOB( const JID& /*from*/, const OOB& oob ); -
virtual void handleLog( LogLevel level, LogArea area, const std::string& message ); -
private: -
Registration *m_reg; -
Client *j; -
CString user_name; -
CString pwd_name; -
BOOL m_isChangePassword; -
};
-
#include"RegisterImpl.h" -
RegTest::RegTest(bool ischangePassword) -
{ -
user_name.Empty(); -
pwd_name.Empty(); -
/*下面的变量用于修改密码时,判断密码是否修改,若修改了就得断开连接*/ -
m_isChangePassword = ischangePassword; -
} -
RegTest::~RegTest() -
{ -
} -
void RegTest::start(CString serverName,CString userName,CString pwd) -
{ -
user_name = userName; -
pwd_name = pwd; -
const std::string server = serverName.operator LPCTSTR(); -
/*注意下面这行代码,当要注册用户时,Client中的变量需要用服务器名,与登录时不同,登录时用的是用户的JID*/ -
j = new Client( server); -
j->disableRoster(); -
j->registerConnectionListener( this ); -
/*下面就是以服务器的指针来创建注册用户的指针,用得到的指针来注册Handler*/ -
m_reg = new Registration( j ); -
m_reg->registerRegistrationHandler( this ); -
j->logInstance().registerLogHandler( LogLevelDebug, LogAreaAll, this ); -
j->connect(); -
delete( m_reg ); -
delete( j ); -
} -
void RegTest::onConnect() -
{ -
/*调用该函数能触发虚函数handleRegistrationFields*/ -
m_reg->fetchRegistrationFields(); -
} -
void RegTest::onDisconnect( ConnectionError e ) -
{ printf( "register_test: disconnected: %d\n", e ); } -
bool RegTest::onTLSConnect( const CertInfo& info ) -
{ -
printf( "status: %d\nissuer: %s\npeer: %s\nprotocol: %s\nmac: %s\ncipher: %s\ncompression: %s\n", -
info.status, info.issuer.c_str(), info.server.c_str(), -
info.protocol.c_str(), info.mac.c_str(), info.cipher.c_str(), -
info.compression.c_str() ); -
return true; -
} -
/*在该函数中完成注册用户*/ -
void RegTest::handleRegistrationFields( const JID& /*from*/, int fields, std::string instructions ) -
{ -
printf( "fields: %d\ninstructions: %s\n", fields, instructions.c_str() ); -
RegistrationFields vals; -
vals.username = user_name; -
vals.password = pwd_name; -
m_reg->createAccount( fields, vals ); -
} -
void RegTest::handleRegistrationResult( const JID& /*from*/, RegistrationResult result ) -
{ -
printf( "result: %d\n", result ); -
if(!m_isChangePassword) -
{ -
j->disconnect(); -
} -
} -
void RegTest::handleAlreadyRegistered( const JID& /*from*/ ) -
{ -
printf( "the account already exists.\n" ); -
} -
void RegTest::handleDataForm( const JID& /*from*/, const DataForm& /*form*/ ) -
{ -
printf( "datForm received\n" ); -
} -
void RegTest::handleOOB( const JID& /*from*/, const OOB& oob ) -
{ -
printf( "OOB registration requested. %s: %s\n", oob.desc().c_str(), oob.url().c_str() ); -
} -
void RegTest::handleLog( LogLevel level, LogArea area, const std::string& message ) -
{ -
printf("log: level: %d, area: %d, %s\n", level, area, message.c_str() ); -
}
登录服务器
要想连接服务器,通常需要下面几个信息:服务器地址(域名或者 IP 地址),服务器端口号,用户帐号,用户密码。在 XMPP 协议中,服务器建议的端口号为5222, 如果没其它必要, 建议采用该端口号。 XMPP 的用户帐号别名叫 JID, JID 惟一确定进行即时消息和在线状态信息通信的独立对象或实体, 并可兼容其他即时通信系统( 如 MSN 等) 相应的实体标识及其在线状态信息。其语法规则为: [节点″@″] 域名[″/″资源], 其中各个域的长度不能超过 1 023字节, 总长度最大为 3 071 字节。从 JID 的定义可以看出来,其实要连接到服务器,JID 中就已经含有了服务器的地址,而如果默认采用 5222 端口号的话,则可以不用提供服务器地址和端口就可以了,而只通过 JID 就可以和服务器连接上。
-
class MessageTest : public ConnectionListener -
{ -
public: -
MessageTest() {} -
virtual ~MessageTest() {} -
void start() -
{ -
//初始化一个 JID,即用户 ID -
JID jid( "userTest@serverTest/test" ); -
//创建一个连接客户端,后一个参数为密码 -
j = new Client( jid, "testPassword" ); -
/*注册连接状态监听器,当调用该方法后, gloox 会在后台自动调用该接口实现中的相应方法。 */ -
j->registerConnectionListener( this ); /*这里用this参数是因为 this 中实现了ConnectionListener 接口,onConnect() 等虚函数函数 */ -
//设置服务 -
j->disco()->setVersion( "messageTest", GLOOX_VERSION, "Linux" ); -
j->disco()->setIdentity( "client", "bot" ); -
//关于数字证书认证方面的东东,照抄就行了。 -
StringList ca; -
ca.push_back( "/path/to/cacert.crt" ); -
j->setCACerts( ca ); -
/*调用 j->connect(false)时,即实现与服务器的连接,即登陆了,连接成功会返回为真。Connect 函数参数为 false 表示不阻塞方式连接,而如果为真,则为阻塞方式连接 */ -
if( j->connect( false ) ) -
{ -
} -
} -
//该该方法即为实现 ConnectionListener 监听器接口中的连接成功的方法实现。 -
virtual void onConnect() -
{ -
printf( "连接服务器成功!!!\n" ); -
} -
/*该该方法即为实现 ConnectionListener 监听器接口中的连接失败或者 断开网络的方法实现*/ -
virtual void onDisconnect( ConnectionError e ) -
{ printf( "断开连接: %d\n", e ); -
delete( j ); -
} -
/*该该方法即为实现 ConnectionListener 监听器接口中的安全连接成功的方法实现。 */ -
virtual bool onTLSConnect( const CertInfo& info ) -
{ -
return true; -
} -
private: -
Client *j;//客户端实例对象 -
}; -
int main( int /*argc*/, char** /*argv*/ )//测试代码 -
{ -
MessageTest *r = new MessageTest(); -
r->start(); -
delete( r ); -
return 0; -
}
考虑到修改密码、修改个人资料,显示好友列表、添加联系人、聊天信息的发送和接收、创建聊天室、传送文件、视频等功能的实现都是在连接登录后才能进行操作,我这里就将登录部分单独出来
-
#include "./src/connectionlistener.h" -
class CQTalkClient; //这个类是一个负责与客户端窗口交流的类,后面会给出 -
using namespace gloox; -
/ -
// CQTalkConnectionListener -
class CQTalkConnectionListener : public gloox::ConnectionListener -
{ -
// Construction -
public: -
CQTalkConnectionListener(); -
CQTalkConnectionListener( CQTalkClient* pClient ); -
virtual ~CQTalkConnectionListener(); -
// Override -
public: -
virtual void onConnect(); -
virtual void onDisconnect(ConnectionError e ); -
virtual bool onTLSConnect( const CertInfo& info ); -
private: -
CIMClient* m_pClient; -
};
-
CQTalkConnectionListener::CQTalkConnectionListener() -
{ -
} -
CQTalkConnectionListener::CQTalkConnectionListener( CQTalkClient* pClient ) -
{ -
m_pClient = NULL; -
ASSERT( pClient ); -
m_pClient = pClient; -
} -
CQTalkConnectionListener::~CQTalkConnectionListener() -
{ -
} -
/ -
// CQTalkConnectionListener override implementation -
void CQTalkConnectionListener::onConnect() -
{ -
ASSERT( m_pClient != NULL ); -
if ( m_pClient != NULL ) -
{ -
m_pClient->OutputLogInfo( "Connecting QTalk server !", CQTalkLogConsole::TEXT_WHITE ); -
} -
} -
void CQTalkConnectionListener::onDisconnect( ConnectionError e ) -
{ -
ASSERT( m_pClient != NULL ); -
switch ( e ) -
{ -
case gloox::ConnNoError : -
m_pClient->OutputLogInfo( "Not really an error. Everything went just fine.", CQTalkLogConsole::TEXT_WHITE ); -
break; -
case gloox::ConnStreamError : -
m_pClient->OutputLogInfo( "A stream error occured. The stream has been closed.", CQTalkLogConsole::TEXT_WHITE ); -
break; -
case gloox::ConnStreamClosed : -
m_pClient->OutputLogInfo( "The stream has been closed graciously.", CQTalkLogConsole::TEXT_WHITE ); -
break; -
case gloox::ConnIoError : -
m_pClient->OutputLogInfo( "An I/O error occured.", CQTalkLogConsole::TEXT_WHITE ); -
break; -
case gloox::ConnOutOfMemory : -
m_pClient->OutputLogInfo( "Out of memory. Uhoh.", CQTalkLogConsole::TEXT_WHITE ); -
break; -
case gloox::ConnNoSupportedAuth : -
m_pClient->OutputLogInfo( "The auth mechanisms the server offers are not supported" \ -
"or the server offered no auth mechanisms at all.", CQTalkLogConsole::TEXT_WHITE ); -
break; -
case gloox::ConnTlsFailed : -
m_pClient->OutputLogInfo( "The server's certificate could not be verified.", CQTalkLogConsole::TEXT_WHITE ); -
break; -
case gloox::ConnAuthenticationFailed : -
m_pClient->OutputLogInfo( "Authentication failed. Username/password wrong or account does not exist.", CQTalkLogConsole::TEXT_WHITE ); -
break; -
case gloox::ConnUserDisconnected : -
m_pClient->OutputLogInfo( "The user (or higher-level protocol) requested a disconnect.", CQTalkLogConsole::TEXT_WHITE ); -
break; -
case gloox::ConnNotConnected : -
m_pClient->OutputLogInfo( "There is no active connection.", CQTalkLogConsole::TEXT_WHITE ); -
break; -
} -
} -
bool CQTalkConnectionListener::onTLSConnect( const CertInfo& info ) -
{ -
return true; -
}
现在我建立一个类CQTalkClient,用来沟通窗口和gloox的内部:
在该类中定义了一个函数用于连接服务器,以及完成gloox所有的注册
-
BOOL CQTalkClient::Connect( CString strID, CString strJID, CString strPwd ) -
{ -
OutputLogInfo( "QTalk applictaion initailze successful !", CQTalkLogConsole::TEXT_WHITE ); -
ASSERT( ! strID.IsEmpty() ); -
ASSERT( ! strJID.IsEmpty() ); -
ASSERT( ! strPwd.IsEmpty() ); -
if ( strID.IsEmpty() || strJID.IsEmpty() || strPwd.IsEmpty() ) -
return FALSE; -
setlocale( LC_ALL, "" ); -
const std::string jabberID = strJID.operator LPCTSTR(); -
const std::string password = strPwd.operator LPCTSTR(); -
gloox::JID jid( jabberID); -
jid.setResource("QTalk"); -
m_pJabberClient = new gloox::Client( jid, password ); -
ASSERT( m_pJabberClient != NULL ); -
if ( m_pJabberClient == NULL ) -
return FALSE; -
m_pQTalkDiscoHandler = new CQTalkDiscoHandler (); -
/*下面得到好友列表相关类指针*/ -
m_pQTalkRosterListener = new CQTalkRosterListener ( this ); -
/*下面得到Log相关类指针*/ -
m_pQTalkLogHandler = new CQTalkLogHandler ( this ); -
/*下面得到会话相关类指针*/ -
m_pQTalkSessionHandler = new CQTalkSessionHandler ( this ); -
/*下面得到连接相关类指针*/ -
m_pQTalkConnectListener = new CQTalkConnectionListener( this ); -
/*下面得到聊天室相关类指针*/ -
m_pQTalkRoom = new QtalkMucRoom (this); -
/*下面得到文件传输相关类指针*/ -
m_pQTalkIBBHandler = new CQTalkIBBHandler ( this ); -
ASSERT( m_pQTalkDiscoHandler != NULL ); -
ASSERT( m_pQTalkRosterListener != NULL ); -
ASSERT( m_pQTalkLogHandler != NULL ); -
ASSERT( m_pQTalkSessionHandler != NULL ); -
ASSERT( m_pQTalkConnectListener != NULL ); -
ASSERT( m_pQTalkIBBHandler != NULL ); -
//m_pJabberClient->setPresence( PresenceAvailable ); -
// m_pJabberClient->setInitialPriority( 4 ); -
/*注册连接状态监听器,当调用该方法后, gloox 会在后台自动调用该接口实现中的相应方法。 */ -
m_pJabberClient->registerConnectionListener( m_pQTalkConnectListener ); -
/*注册好友列表监听器*/ -
m_pJabberClient->rosterManager()->registerRosterListener( m_pQTalkRosterListener ); -
m_pJabberClient->disco()->setVersion( "QTalk", GLOOX_VERSION ,"Windows"); -
m_pJabberClient->disco()->setIdentity( "client", "Qtalk" ); -
/*注册log监听器*/ -
m_pJabberClient->logInstance().registerLogHandler( LogLevelDebug, LogAreaAll, m_pQTalkLogHandler ); -
/*注册聊天室监听器*/ -
m_pJabberClient->registerMUCInvitationHandler( m_pQTalkRoom ); -
/*注册会话消息监听器*/ -
m_pJabberClient->registerMessageSessionHandler(m_pQTalkSessionHandler); -
if ( m_pJabberClient->connect( false ) == false ) -
{ -
ReleaseRes(); -
return FALSE; -
} -
/*戏码得到名片相关类的指针*/ -
m_pQTalkVCard = new VCardTest(this); -
/*下面得到文件管理相关类指针*/ -
m_pIBBManager = new gloox::InBandBytestreamManager( m_pJabberClient, m_pJabberClient->disco() ); -
/*注册文件传输的监听器*/ -
m_pIBBManager->registerInBandBytestreamHandler( m_pQTalkIBBHandler ); -
m_jid = jabberID; -
AfxGetMainWnd()->SetWindowText( m_jid.c_str() ); -
/*下面是一个线程,该线程用于接收发过来的信息和数据*/ -
m_pQTalkThread = AfxBeginThread( QTalkMsgHandlerProc, this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED ); -
ASSERT_VALID( m_pQTalkThread ); -
if ( ! m_pQTalkThread ) -
return FALSE; -
m_pQTalkThread->ResumeThread(); -
OutputLogInfo( "Connect server successful !", CQTalkLogConsole::TEXT_WHITE ); -
return TRUE; -
} -
线程函数的实现: -
UINT CQTalkClient::QTalkMsgHandlerProc( LPVOID lParam ) -
{ -
CQTalkClient* pQTalkClient = static_cast< CQTalkClient* >( lParam ); -
ASSERT( pQTalkClient != NULL ); -
if ( pQTalkClient == NULL ) -
return 1; -
pQTalkClient->OutputLogInfo( "Start LISTENER thread !", CQTalkLogConsole::TEXT_RED ); -
ASSERT( pQTalkClient->m_pQTalkDiscoHandler != NULL ); -
ASSERT( pQTalkClient->m_pQTalkLogHandler != NULL ); -
ASSERT( pQTalkClient->m_pQTalkSessionHandler != NULL ); -
ASSERT( pQTalkClient->m_pQTalkConnectListener != NULL ); -
ASSERT( pQTalkClient->m_pJabberClient != NULL ); -
gloox::ConnectionError ce = gloox::ConnNoError; -
while ( TRUE ) -
{ -
DWORD dwFlag = ::WaitForSingleObject( CQTalkClient::s_QTalkEvent.m_hObject, 0 ); -
if ( dwFlag == WAIT_OBJECT_0 ) -
{ -
pQTalkClient->OutputLogInfo( "End LISTENER thread !", CQTalkLogConsole::TEXT_RED ); -
break; -
} -
ce = pQTalkClient->m_pJabberClient->recv(); -
} -
return 0; -
}
修改用户登录密码
在CQTalkClient函数中添加一个函数用于修改密码
-
VOID CQTalkClient::SetPassword(CString password) -
{ -
const std::string pwd = password.operator LPCTSTR(); -
rr = new RegTest(TRUE); -
//rr->changepassword(serverName,useName,password); -
Registration *m_reg = new Registration(m_pJabberClient); -
m_reg->registerRegistrationHandler(rr); -
m_reg->changePassword( m_pJabberClient->username(), password.operator LPCTSTR() ); -
::MessageBox(NULL,"修改密码成功!",NULL,0); -
delete (m_reg); -
}
修改个人资料
-
#include "./src/client.h" -
#include "./src/connectionlistener.h" -
#include "./src/disco.h" -
#include "./src/stanza.h" -
#include "./src/gloox.h" -
#include "./src/loghandler.h" -
#include "./src/vcardhandler.h" -
#include "./src/vcardmanager.h" -
#include "./src/vcard.h" -
using namespace gloox; -
#include -
#include -
#include -
class CQTalkClient; -
struct vcard_info -
{ -
std::string username; -
std::string servername; -
std::string nickname; -
// std::list AddressList; -
std::string street; -
std::string family; -
std::string given; -
std::string middle; -
}; -
class VCardTest: public VCardHandler/*,ConnectionListener*/ -
{ -
public: -
VCardTest(void); -
VCardTest(CQTalkClient* pClient); -
~VCardTest(void); -
public: -
void start(CString m_strjid); -
void store(CString &,CString &,CString &); -
//virtual void onConnect(); -
//virtual void onDisconnect( ConnectionError e ) ; -
//virtual bool onTLSConnect( const CertInfo& info ); -
//virtual void handleDiscoInfoResult( Stanza */*stanza*/, int /*context*/ ); -
//virtual void handleDiscoItemsResult( Stanza */*stanza*/, int /*context*/ ); -
virtual void handleDiscoError( Stanza */*stanza*/, int /*context*/ ); -
//virtual void handleLog( LogLevel level, LogArea area, const std::string& message ); -
virtual void handleVCard( const JID& jid, VCard *vcard); -
virtual void handleVCardResult(VCardContext context, const JID& jid,StanzaError se = StanzaErrorUndefined ); -
//Client *j; -
VCardManager *m_vManager; -
int m_count; -
CString strJID; -
public: -
struct vcard_info *str; -
// static CString m_strFetch; -
CString m_strSet; -
// AddressList& m_addressList; -
BOOL m_choice; -
private: -
CQTalkClient* m_pClient; -
};
-
VCardTest::VCardTest(void) -
{ -
// m_pClient = NULL; -
} -
VCardTest::VCardTest(CQTalkClient* pClient) -
{ -
// m_count = 0; -
str = NULL; -
strJID.Empty(); -
m_pClient = pClient; -
m_choice = TRUE; -
m_vManager = new VCardManager( m_pClient->GetClient()); -
} -
VCardTest::~VCardTest(void) -
{ -
delete(m_vManager); -
} -
void VCardTest::start(CString m_strjid) -
{ -
strJID = m_strjid; -
std::string strjid = m_strjid.operator LPCTSTR(); -
JID jid( strjid ); -
m_vManager->fetchVCard( strjid, this ); -
} -
void VCardTest::store(CString &nickname,CString &servername,CString &street) -
{ -
std::string m_strjid = strJID.operator LPCTSTR(); -
JID jid(m_strjid); -
VCard *v = new VCard(); -
v->setFormattedname( "Hurk the Hurk" ); -
v->setNickname( nickname.operator LPCTSTR()); -
v->setName( "Simpson", "Bart", "", "Mr.", "jr." ); -
v->addAddress( "pobox", "app. 2", (street.operator LPCTSTR()), "Springfield", "region", "123", "USA", VCard::AddrTypeHome ); -
m_vManager->storeVCard( v, this ); -
m_vManager->fetchVCard( m_strjid, this ); -
} -
void VCardTest::handleVCard( const JID& jid, VCard *vcard ) -
{ -
std::string m_strjid = strJID.operator LPCTSTR(); -
// ++m_count; -
if( !vcard ) -
{ -
printf( "empty vcard!\n" ); -
return; -
} -
printf( "received vcard for %s: %s\n", jid.full().c_str(), vcard->tag()->xml().c_str()); -
// ::AfxMessageBox(jid.full().c_str()); -
// ::AfxMessageBox(vcard->tag()->xml().c_str()); -
// m_vManager->fetchVCard( jid, this ); -
str = new vcard_info; -
str ->username = jid.username().c_str(); -
str ->servername = jid.server().c_str(); -
str ->nickname = vcard->nickname().c_str(); -
str->family = vcard->name().family; -
str->given = vcard->name().given; -
str->middle = vcard->name().middle; -
VCard::AddressList::const_iterator it = vcard->addresses().begin(); -
for( ; it != vcard->addresses().end(); ++it ) -
{ -
// printf( "address: %s\n", (*it).street.c_str() ); -
str ->street = (*it).street.c_str(); -
} -
AfxGetMainWnd()->SendMessage( \ -
QTalkGlobal::WM_QTALK_VCARD, \ -
NULL, \ -
(LPARAM)str ); -
delete(str); -
} -
void VCardTest::handleVCardResult( VCardContext context, const JID& jid,StanzaError se) -
{ -
//se = StanzaErrorUndefined; -
//printf( "vcard result: context: %d, jid: %s, error: %d\n", context, jid.full().c_str(), se ); -
// m_vManager->fetchVCard( jid, this ); -
}
然后只需在CQTalkClient中添加一个函数:
-
VOID CQTalkClient::VCard(CString m_strjid/*,CString m_strPwd*/) -
{ -
m_pQTalkVCard->start(m_strjid); -
}
添加联系人
在CQTalkClient中添加函数
-
VOID CQTalkClient::AddConnecter(CString m_jid,CString m_group) -
{ -
m_cf = TRUE; -
m_delete = FALSE; -
const std::string m_strjid = m_jid.operator LPCTSTR(); -
m_strGroup = m_group; -
JID jid(m_strjid); -
m_pJabberClient->rosterManager()->subscribe(jid); -
}
关于添加联系人的类:
-
#include "./src/rosterlistener.h" -
#include "./src/rostermanager.h" -
class CQTalkClient; -
using namespace gloox; -
class CQTalkRosterListener : public gloox::RosterListener -
{ -
// Construction -
public: -
CQTalkRosterListener(); -
CQTalkRosterListener( CQTalkClient* pClient); -
virtual ~CQTalkRosterListener(); -
// Implementation -
private: -
virtual void handleItemSubscribed ( const JID& jid ); -
virtual void handleItemUnsubscribed( const JID& jid); -
virtual void handleItemAdded ( const JID& jid ); -
virtual void handleItemRemoved( const JID& jid ); -
virtual void handleItemUpdated( const JID& jid ); -
virtual void handleRoster( const Roster& roster ); -
virtual void handleRosterPresence( const RosterItem& item, const std::string& resource,Presence presence, const std::string& msg ); -
virtual bool handleSubscriptionRequest ( const JID& jid, const std::string& msg ); -
virtual bool handleUnsubscriptionRequest( const JID& jid, const std::string& msg ); -
virtual void handleRosterError( Stanza* stanza ); -
virtual void handleNonrosterPresence( Stanza* stanza ); -
virtual void handleSelfPresence( const RosterItem& item, const std::string& resource,Presence presence, const std::string& msg ); -
// Implementation -
private: -
CQTalkClient* m_pClient; -
};
-
CQTalkRosterListener::CQTalkRosterListener() -
{ -
m_pClient = NULL; -
} -
CQTalkRosterListener::CQTalkRosterListener(CQTalkClient* pClient ) -
{ -
m_pClient=pClient; -
} -
CQTalkRosterListener::~CQTalkRosterListener() -
{ -
} -
/ -
// CQTalkRosterListener method implementation -
void CQTalkRosterListener::handleItemSubscribed( const JID& jid ) -
{ -
m_pClient->OutputLogInfo( "RosterListener::itemSubscribed", CQTalkLogConsole::TEXT_WHITE ); -
AfxGetMainWnd()->PostMessage( \ -
QTalkGlobal::WM_QTALK_MESSAGE, \ -
QTalkGlobal::WM_QTALK_ROSTER, \ -
QTalkGlobal::ROSTER_LIST_ALL ); -
// m_pClient->m_cf = FALSE; -
} -
void CQTalkRosterListener::handleItemUnsubscribed(const JID& jid) -
{ -
} -
void CQTalkRosterListener::handleItemAdded( const JID& jid ) -
{ -
m_pClient->OutputLogInfo( "RosterListener::itemAdded", CQTalkLogConsole::TEXT_WHITE ); -
RosterItem* rostitem = m_pClient->GetClient()->rosterManager()->getRosterItem(jid); -
QTalkGlobal::ROSTER rosterItem; -
rosterItem.jid = rostitem->jid(); -
rosterItem.name = rostitem->name(); -
rosterItem.subsciption = rostitem->subscription(); -
rosterItem.groups.push_back((m_pClient->m_strGroup).operator LPCTSTR()); -
m_pClient->m_rosterList.push_back( rosterItem ); -
StringList g; -
g.push_back((m_pClient->m_strGroup).operator LPCTSTR()); -
m_pClient->GetClient()->rosterManager()->add(jid,rostitem->name(),g); -
} -
void CQTalkRosterListener::handleItemRemoved(const JID& jid ) -
{ -
m_pClient->OutputLogInfo( "RosterListener::itemRemoved", CQTalkLogConsole::TEXT_WHITE ); -
if(m_pClient->m_delete) -
{ -
QTalkGlobal::CIT_ROSTER_LIST i; -
i = m_pClient->m_rosterList.begin(); -
while(i != m_pClient->m_rosterList.end()) -
{ -
QTalkGlobal::ROSTER rosterItem = *i; -
if(rosterItem.jid == jid.full()) -
{ -
m_pClient->m_rosterList.erase(i++); -
} -
else -
{ -
i++; -
} -
} -
AfxGetMainWnd()->SendMessage( \ -
QTalkGlobal::WM_QTALK_MESSAGE, \ -
QTalkGlobal::WM_QTALK_ROSTER, \ -
QTalkGlobal::ROSTER_DELETE_ITEM ); -
} -
} -
void CQTalkRosterListener::handleItemUpdated( const JID& jid) -
{ -
m_pClient->OutputLogInfo( "RosterListener::itemUpdated", CQTalkLogConsole::TEXT_WHITE ); -
if(!m_pClient->m_cf) -
{ -
AfxGetMainWnd()->PostMessage( \ -
QTalkGlobal::WM_QTALK_MESSAGE, \ -
QTalkGlobal::WM_QTALK_ROSTER, \ -
QTalkGlobal::ROSTER_LIST_ALL ); -
// m_pClient->m_cf = TRUE; -
} -
} -
// By calling this method -
// you can get all roster from the server -
void CQTalkRosterListener::handleRoster( const Roster& roster ) -
{ -
m_pClient->OutputLogInfo( "Manager the roster !", CQTalkLogConsole::TEXT_WHITE ); -
Roster::const_iterator it = roster.begin(); -
m_pClient->m_rosterList.clear(); -
QTalkGlobal::ROSTER rosterItem; -
for ( ; it != roster.end(); it++ ) -
{ -
m_pClient->OutputLogInfo((*it).second->jid().c_str(),CQTalkLogConsole::TEXT_PURPLE ); -
m_pClient->OutputLogInfo((*it).second->name().c_str(), CQTalkLogConsole::TEXT_PURPLE ); -
//m_pClient->OutputLogInfo((*it).second->subscription(), CQTalkLogConsole::TEXT_PURPLE ); -
StringList g = (*it).second->groups(); -
StringList::const_iterator it_g = g.begin(); -
for( ; it_g != g.end(); ++it_g ) -
{ -
std::string msg; -
CCodeLib::UTF8ToGB2312( msg, ( *it_g ).c_str(), ( *it_g ).length() ); -
m_pClient->OutputLogInfo( msg.c_str(), CQTalkLogConsole::TEXT_YELLOW ); -
} -
rosterItem.jid = ( *it ).second->jid(); -
rosterItem.name = ( *it ).second->name(); -
rosterItem.subsciption = ( *it ).second->subscription(); -
rosterItem.groups = ( *it ).second->groups(); -
rosterItem.presence = 6; -
m_pClient->m_rosterList.push_back( rosterItem ); -
} -
AfxGetMainWnd()->PostMessage( \ -
QTalkGlobal::WM_QTALK_MESSAGE, \ -
QTalkGlobal::WM_QTALK_ROSTER, \ -
QTalkGlobal::ROSTER_LIST_ALL ); -
} -
// The rosters are not online or online -
// calling these method to implement roster update... -
void CQTalkRosterListener::handleRosterPresence( const RosterItem& item,const std::string& resource,Presence presence, const std::string& msg ) -
{ -
m_pClient->OutputLogInfo( "RosterListener::presenceUpdated", CQTalkLogConsole::TEXT_WHITE ); -
QTalkGlobal::CIT_ROSTER_LIST cit = m_pClient->m_rosterList.begin(); -
for(;cit != m_pClient->m_rosterList.end(); cit++) -
{ -
if(cit->jid == item.jid()) -
{ -
cit->presence = presence; -
} -
} -
AfxGetMainWnd()->SendMessage( \ -
QTalkGlobal::WM_QTALK_MESSAGE, \ -
QTalkGlobal::WM_QTALK_ROSTER, \ -
QTalkGlobal::ROSTER_PRESENCEUPDATE ); -
} -
bool CQTalkRosterListener::handleSubscriptionRequest( const JID& jid, const std::string& msg ) -
{ -
m_pClient->OutputLogInfo( "RosterListener::subscriptionRequest", CQTalkLogConsole::TEXT_WHITE ); -
// m_pClient->m_cf = FALSE; -
if(!m_pClient->m_cf) -
{ -
AfxGetMainWnd()->SendMessage( \ -
QTalkGlobal::WM_QTALK_MESSAGE, \ -
QTalkGlobal::WM_QTALK_ROSTER, \ -
QTalkGlobal::ROSTER_SUBSCRIPTIONREQUEST); -
} -
if(!m_pClient->m_choice) -
{ -
m_pClient->GetClient()->rosterManager()->unsubscribe(jid); -
} -
m_pClient->m_cf = FALSE; -
return true; -
} -
bool CQTalkRosterListener::handleUnsubscriptionRequest( const JID& jid, const std::string& msg ) -
{ -
m_pClient->OutputLogInfo( "RosterListener::unsubscriptionRequest", CQTalkLogConsole::TEXT_WHITE ); -
return true; -
} -
void CQTalkRosterListener::handleRosterError( Stanza* stanza ) -
{ -
} -
void CQTalkRosterListener::handleNonrosterPresence( Stanza* stanza ) -
{ -
} -
void CQTalkRosterListener::handleSelfPresence( const RosterItem& item, const std::string& resource,Presence presence, const std::string& msg ) -
{ -
}
聊天室:
-
#include "./src/client.h" -
#include "./src/connectionlistener.h" -
#include "./src/mucroomhandler.h" -
#include "./src/mucroom.h" -
#include "./src/disco.h" -
#include "./src/stanza.h" -
#include "./src/dataform.h" -
#include "./src/gloox.h" -
#include "./src/lastactivity.h" -
#include "./src/loghandler.h" -
#include "./src/logsink.h" -
#include "./src/mucinvitationhandler.h" -
using namespace gloox; -
#include -
#include -
#include -
#ifdef WIN32 -
#include -
#endif -
class CQTalkClient; -
class QTalkMucRoom : public MUCRoomHandler,public gloox::MUCInvitationHandler -
{ -
public: -
QTalkMucRoom(); -
QTalkMucRoom( CQTalkClient* pClient); -
~QTalkMucRoom(); -
public: -
void start(CString roomName); -
void ToRoom(CString str,CString msg); -
void OnChatSession( std::string nick, std::string message ); -
void SendToRoom(CString message); -
void ServerRoom(); -
private: -
virtual void handleMUCParticipantPresence( MUCRoom * /*room*/, const MUCRoomParticipant participant, -
Presence presence ); -
virtual void handleMUCMessage( MUCRoom* /*room*/, const std::string& nick, const std::string& message, -
bool history, const std::string& /*when*/, bool priv ); -
virtual void handleMUCSubject( MUCRoom * /*room*/, const std::string& nick, const std::string& subject ); -
virtual void handleMUCError( MUCRoom * /*room*/, StanzaError error ); -
virtual void handleMUCInfo( MUCRoom * /*room*/, int features, const std::string& name, -
const DataForm *infoForm ); -
virtual void handleMUCItems( MUCRoom * /*room*/, const StringMap& items ); -
virtual void handleMUCInviteDecline( MUCRoom * /*room*/, const JID& invitee, const std::string& reason ); -
virtual bool handleMUCRoomCreation( MUCRoom *room ); -
virtual void handleMUCInvitation( const JID& room, const JID& invitee, const std::string& reason, -
const std::string& body, const std::string& password, -
bool cont ); -
private: -
MUCRoom *m_room; -
MUCRoom *m_serverRoom; -
CQTalkClient* m_pClient; -
BOOL m_send; -
BOOL m_server; -
};
-
#include "StdAfx.h" -
#include "QTalkMucRoom.h" -
#include "QTalkClient.h" -
QTalkMucRoom::QTalkMucRoom() -
{ -
// m_pClient = NULL; -
} -
QTalkMucRoom::QTalkMucRoom(CQTalkClient* pClient) -
{ -
m_room = NULL; -
m_serverRoom = NULL; -
m_pClient = pClient; -
m_send = TRUE; -
m_server = TRUE; -
} -
QTalkMucRoom::~QTalkMucRoom() -
{ -
delete( m_room ); -
delete( m_serverRoom); -
} -
void QTalkMucRoom::start(CString roomName) -
{ -
const std::string strjid = roomName.operator LPCTSTR(); -
m_server = TRUE; -
JID nick(strjid); -
m_room = new MUCRoom( m_pClient->GetClient(), nick, this, 0 ); -
m_room->join(); -
m_room->getRoomInfo(); -
m_room->getRoomItems(); -
// delete(m_room); -
} -
void QTalkMucRoom::ServerRoom() -
{ -
m_server = FALSE; -
JID nick("conference.upower-a448cf28"); -
m_serverRoom = new MUCRoom( m_pClient->GetClient(), nick, this, 0); -
m_serverRoom->getRoomItems(); -
// delete( m_room ); -
} -
void QTalkMucRoom::ToRoom(CString str,CString msg) -
{ -
const std::string strjid = str.operator LPCTSTR(); -
JID jid(strjid); -
m_room->invite(jid,msg.operator LPCTSTR()); -
} -
void QTalkMucRoom::SendToRoom(CString message) -
{ -
m_send = FALSE; -
const std::string strMessage = message.operator LPCTSTR(); -
m_room->send(strMessage); -
} -
void QTalkMucRoom::handleMUCParticipantPresence( MUCRoom * /*room*/, const MUCRoomParticipant participant, -
Presence presence ) -
{ -
std::string str = m_pClient->GetJID(); -
if( presence == PresenceAvailable ) -
{ -
// printf( "!!!!!!!!!!!!!!!! %s is in the room, too\n", participant.nick->resource().c_str() ); -
if(str.compare(participant.jid->bare())) -
{ -
AfxGetMainWnd()->PostMessage( \ -
QTalkGlobal::WM_QTALK_CONNECT, \ -
QTalkGlobal::CONECT_PRESENCE_AVAILABLE, \ -
NULL); -
} -
} -
else if( presence == PresenceUnavailable ) -
printf( "!!!!!!!!!!!!!!!! %s left the room\n", participant.nick->resource().c_str() ); -
else -
printf( "Presence is %d of %s\n", presence, participant.nick->resource().c_str() ); -
} -
void QTalkMucRoom::handleMUCMessage( MUCRoom* /*room*/, const std::string& nick, const std::string& message, -
bool history, const std::string& /*when*/, bool priv ) -
{ -
//printf( "%s said: '%s' (history: %s, private: %s)\n", nick.c_str(), message.c_str(), -
// history ? "yes" : "no", priv ? "yes" : "no" ); -
if(m_send) -
{ -
OnChatSession(nick,message); -
} -
m_send = TRUE; -
} -
void QTalkMucRoom::handleMUCSubject( MUCRoom * /*room*/, const std::string& nick, const std::string& subject ) -
{ -
if( nick.empty() ) -
printf( "Subject: %s\n", subject.c_str() ); -
else -
printf( "%s has set the subject to: '%s'\n", nick.c_str(), subject.c_str() ); -
} -
void QTalkMucRoom::handleMUCError( MUCRoom * /*room*/, StanzaError error ) -
{ -
printf( "!!!!!!!!got an error: %d", error ); -
} -
void QTalkMucRoom::handleMUCInfo( MUCRoom * /*room*/, int features, const std::string& name, -
const DataForm *infoForm ) -
{ -
// printf( "features: %d, name: %s, form xml: %s\n", features, name.c_str(), infoForm->tag()->xml().c_str() ); -
} -
void QTalkMucRoom::handleMUCItems( MUCRoom * /*room*/, const StringMap& items ) -
{ -
StringMap::const_iterator it = items.begin(); -
for( ; it != items.end(); ++it ) -
{ -
// printf( "%s -- %s is an item here\n", (*it).first.c_str(), (*it).second.c_str() ); -
m_pClient->m_serverRoomList.push_back((*it).first); -
} -
if(!m_server) -
{ -
AfxGetMainWnd()->PostMessage( \ -
QTalkGlobal::WM_QTALK_CHATROOM, \ -
QTalkGlobal::WM_QTALK_SERVERCHATROOMLIST, \ -
QTalkGlobal::SERVERCHATROOM_LIST); -
} -
} -
void QTalkMucRoom::handleMUCInviteDecline( MUCRoom * /*room*/, const JID& invitee, const std::string& reason ) -
{ -
printf( "Invitee %s declined invitation. reason given: %s\n", invitee.full().c_str(), reason.c_str() ); -
} -
bool QTalkMucRoom::handleMUCRoomCreation( MUCRoom *room ) -
{ -
// printf( "room %s didn't exist, beeing created.\n", room->name().c_str() ); -
return true; -
} -
void QTalkMucRoom::handleMUCInvitation( const JID& room, const JID& invitee, const std::string& reason, -
const std::string& body, const std::string& password, -
bool cont ) -
{ -
// int i = 0; -
const std::string strUsr = room.username(); -
const std::string strInvitee = room.username(); -
CString str = _T(""); -
str.Format("%s@conference.upower-a448cf28/%s",strUsr.c_str(),strInvitee.c_str()); -
JID nick(str.operator LPCTSTR()); -
MUCRoom* m_serverRoom1 = new MUCRoom( m_pClient->GetClient(), nick, this, 0); -
m_room->join(); -
// m_room = new MUCRoom( m_pClient->GetClient(), room, this, 0); -
//m_room->join(); -
//JID jid("test@upower-a448cf28"); -
//m_pClient->GetClient()->registerPresenceHandler(jid,this); -
} -
void QTalkMucRoom::OnChatSession( std::string nick, std::string message ) -
{ -
m_pClient->m_nick = nick; -
m_pClient->m_rMessage = message; -
AfxGetMainWnd()->SendMessage(\ -
QTalkGlobal::WM_QTALK_CHATROOM, \ -
QTalkGlobal::WM_QTALK_ROOMSESSION, \ -
QTalkGlobal::CHATROOM_MSG -
); -
} -
