gloox开发

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通信的操作都在该动态库中完成,与对窗口的操作进行分开。

 

下面开始为该工程添加文件,完成即时通信中的用户注册、登录、修改密码、修改个人资料,显示好友列表、添加联系人、聊天信息的发送和接收、创建聊天室、传送文件、视频等功能。

用户注册

 

 
  1. </pre><pre name="code" class="cpp">#include "./src/client.h"

  2. #include "./src/connectionlistener.h"

  3. #include "./src/registration.h"

  4. #include "./src/logsink.h"

  5. #include "./src/loghandler.h"

  6.  
  7. using namespace gloox;

  8. #include <iostream>

  9. #include "afxmt.h"

  10.  
  11. class RegTest : public RegistrationHandler, ConnectionListener, LogHandler

  12. {

  13. public:

  14. RegTest(bool ischangePassword) ;

  15. virtual ~RegTest();

  16.  
  17. void start(CString serverName,CString userName,CString pwd);

  18. virtual void onConnect();

  19. virtual void onDisconnect( ConnectionError e );

  20. virtual bool onTLSConnect( const CertInfo& info );

  21. virtual void handleRegistrationFields( const JID& /*from*/, int fields, std::string instructions );

  22. virtual void handleRegistrationResult( const JID& /*from*/, RegistrationResult result );

  23. virtual void handleAlreadyRegistered( const JID& /*from*/ );

  24. virtual void handleDataForm( const JID& /*from*/, const DataForm& /*form*/ );

  25. virtual void handleOOB( const JID& /*from*/, const OOB& oob );

  26. virtual void handleLog( LogLevel level, LogArea area, const std::string& message );

  27.  
  28. private:

  29. Registration *m_reg;

  30. Client *j;

  31. CString user_name;

  32. CString pwd_name;

  33. BOOL m_isChangePassword;

  34. };

 
  1. #include"RegisterImpl.h"

  2.  
  3. RegTest::RegTest(bool ischangePassword)

  4. {

  5. user_name.Empty();

  6. pwd_name.Empty();

  7. /*下面的变量用于修改密码时,判断密码是否修改,若修改了就得断开连接*/

  8. m_isChangePassword = ischangePassword;

  9. }

  10.  
  11. RegTest::~RegTest()

  12. {

  13. }

  14.  
  15. void RegTest::start(CString serverName,CString userName,CString pwd)

  16. {

  17. user_name = userName;

  18. pwd_name = pwd;

  19.  
  20. const std::string server = serverName.operator LPCTSTR();

  21. /*注意下面这行代码,当要注册用户时,Client中的变量需要用服务器名,与登录时不同,登录时用的是用户的JID*/

  22. j = new Client( server);

  23. j->disableRoster();

  24. j->registerConnectionListener( this );

  25.  
  26. /*下面就是以服务器的指针来创建注册用户的指针,用得到的指针来注册Handler*/

  27. <span style="white-space:pre"> </span>m_reg = new Registration( j );

  28. m_reg->registerRegistrationHandler( this );

  29.  
  30. j->logInstance().registerLogHandler( LogLevelDebug, LogAreaAll, this );

  31.  
  32. j->connect();

  33.  
  34. delete( m_reg );

  35. delete( j );

  36. }

  37.  
  38.  
  39. void RegTest::onConnect()

  40. {

  41. /*调用该函数能触发虚函数handleRegistrationFields*/

  42. m_reg->fetchRegistrationFields();

  43. }

  44.  
  45. void RegTest::onDisconnect( ConnectionError e )

  46. { printf( "register_test: disconnected: %d\n", e ); }

  47.  
  48. bool RegTest::onTLSConnect( const CertInfo& info )

  49. {

  50. printf( "status: %d\nissuer: %s\npeer: %s\nprotocol: %s\nmac: %s\ncipher: %s\ncompression: %s\n",

  51. info.status, info.issuer.c_str(), info.server.c_str(),

  52. info.protocol.c_str(), info.mac.c_str(), info.cipher.c_str(),

  53. info.compression.c_str() );

  54. return true;

  55. }

  56. /*在该函数中完成注册用户*/

  57. void RegTest::handleRegistrationFields( const JID& /*from*/, int fields, std::string instructions )

  58. {

  59. printf( "fields: %d\ninstructions: %s\n", fields, instructions.c_str() );

  60. RegistrationFields vals;

  61. vals.username = user_name;

  62. vals.password = pwd_name;

  63. m_reg->createAccount( fields, vals );

  64. }

  65.  
  66. void RegTest::handleRegistrationResult( const JID& /*from*/, RegistrationResult result )

  67. {

  68. printf( "result: %d\n", result );

  69. if(!m_isChangePassword)

  70. {

  71. j->disconnect();

  72. }

  73. }

  74.  
  75. void RegTest::handleAlreadyRegistered( const JID& /*from*/ )

  76. {

  77. printf( "the account already exists.\n" );

  78. }

  79.  
  80. void RegTest::handleDataForm( const JID& /*from*/, const DataForm& /*form*/ )

  81. {

  82. printf( "datForm received\n" );

  83. }

  84.  
  85. void RegTest::handleOOB( const JID& /*from*/, const OOB& oob )

  86. {

  87. printf( "OOB registration requested. %s: %s\n", oob.desc().c_str(), oob.url().c_str() );

  88. }

  89.  
  90. void RegTest::handleLog( LogLevel level, LogArea area, const std::string& message )

  91. {

  92. printf("log: level: %d, area: %d, %s\n", level, area, message.c_str() );

  93. }

 

登录服务器

要想连接服务器,通常需要下面几个信息:服务器地址(域名或者 IP 地址),服务器端口号,用户帐号,用户密码。在 XMPP 协议中,服务器建议的端口号为5222, 如果没其它必要, 建议采用该端口号。 XMPP 的用户帐号别名叫 JID, JID 惟一确定进行即时消息和在线状态信息通信的独立对象或实体, 并可兼容其他即时通信系统( 如 MSN 等) 相应的实体标识及其在线状态信息。其语法规则为: [节点″@″] 域名[″/″资源], 其中各个域的长度不能超过 1 023字节, 总长度最大为 3 071 字节。从 JID 的定义可以看出来,其实要连接到服务器,JID 中就已经含有了服务器的地址,而如果默认采用 5222 端口号的话,则可以不用提供服务器地址和端口就可以了,而只通过 JID 就可以和服务器连接上。

 
  1. class MessageTest : public ConnectionListener

  2. {

  3. public:

  4. MessageTest() {}

  5. virtual ~MessageTest() {}

  6. void start()

  7. {

  8. //初始化一个 JID,即用户 ID

  9. JID jid( "userTest@serverTest/test" );

  10. <span style="white-space:pre"> </span>//创建一个连接客户端,后一个参数为密码

  11. j = new Client( jid, "testPassword" );

  12. <span style="white-space:pre"> </span>/*注册连接状态监听器,当调用该方法后, gloox 会在后台自动调用该接口实现中的相应方法。 */

  13. j->registerConnectionListener( this ); /*这里用this参数是因为 this 中实现了ConnectionListener 接口,onConnect() 等虚函数函数 */

  14. <span style="white-space:pre"> </span>//设置服务

  15. j->disco()->setVersion( "messageTest", GLOOX_VERSION, "Linux" );

  16. j->disco()->setIdentity( "client", "bot" );

  17. //关于数字证书认证方面的东东,照抄就行了。

  18. StringList ca;

  19. ca.push_back( "/path/to/cacert.crt" );

  20. j->setCACerts( ca );

  21. /*调用 j->connect(false)时,即实现与服务器的连接,即登陆了,连接成功会返回为真。Connect 函数参数为 false 表示不阻塞方式连接,而如果为真,则为阻塞方式连接 */

  22. if( j->connect( false ) )

  23. {

  24. }

  25. }

  26. //该该方法即为实现 ConnectionListener 监听器接口中的连接成功的方法实现。

  27. virtual void onConnect()

  28. {

  29. printf( "连接服务器成功!!!\n" );

  30. }

  31. /*该该方法即为实现 ConnectionListener 监听器接口中的连接失败或者 断开网络的方法实现*/

  32. virtual void onDisconnect( ConnectionError e )

  33. { printf( "断开连接: %d\n", e );

  34. delete( j );

  35. }

  36. /*该该方法即为实现 ConnectionListener 监听器接口中的安全连接成功的方法实现。 */

  37. virtual bool onTLSConnect( const CertInfo& info )

  38. {

  39. return true;

  40. }

  41. private:

  42. Client *j;//客户端实例对象

  43. };

  44. int main( int /*argc*/, char** /*argv*/ )//测试代码

  45. {

  46. MessageTest *r = new MessageTest();

  47. r->start();

  48. delete( r );

  49. return 0;

  50. }

 

考虑到修改密码、修改个人资料,显示好友列表、添加联系人、聊天信息的发送和接收、创建聊天室、传送文件、视频等功能的实现都是在连接登录后才能进行操作,我这里就将登录部分单独出来

 
  1. #include "./src/connectionlistener.h"

  2.  
  3. class CQTalkClient; //这个类是一个负责与客户端窗口交流的类,后面会给出

  4. using namespace gloox;

  5. /

  6. // CQTalkConnectionListener

  7.  
  8. class CQTalkConnectionListener : public gloox::ConnectionListener

  9. {

  10. // Construction

  11. public:

  12. CQTalkConnectionListener();

  13. CQTalkConnectionListener( CQTalkClient* pClient );

  14. virtual ~CQTalkConnectionListener();

  15.  
  16. // Override

  17. public:

  18. virtual void onConnect();

  19. virtual void onDisconnect(ConnectionError e );

  20. virtual bool onTLSConnect( const CertInfo& info );

  21.  
  22. private:

  23. CIMClient* m_pClient;

  24. };

 

 
  1. CQTalkConnectionListener::CQTalkConnectionListener()

  2. {

  3. }

  4.  
  5. CQTalkConnectionListener::CQTalkConnectionListener( CQTalkClient* pClient )

  6. {

  7. m_pClient = NULL;

  8. ASSERT( pClient );

  9.  
  10. m_pClient = pClient;

  11. }

  12.  
  13. CQTalkConnectionListener::~CQTalkConnectionListener()

  14. {

  15. }

  16.  
  17. /

  18. // CQTalkConnectionListener override implementation

  19.  
  20. void CQTalkConnectionListener::onConnect()

  21. {

  22. ASSERT( m_pClient != NULL );

  23. if ( m_pClient != NULL )

  24. {

  25. m_pClient->OutputLogInfo( "Connecting QTalk server !", CQTalkLogConsole::TEXT_WHITE );

  26. }

  27.  
  28. }

  29.  
  30. void CQTalkConnectionListener::onDisconnect( ConnectionError e )

  31. {

  32. ASSERT( m_pClient != NULL );

  33.  
  34. switch ( e )

  35. {

  36. case gloox::ConnNoError :

  37. m_pClient->OutputLogInfo( "Not really an error. Everything went just fine.", CQTalkLogConsole::TEXT_WHITE );

  38. break;

  39.  
  40. case gloox::ConnStreamError :

  41. m_pClient->OutputLogInfo( "A stream error occured. The stream has been closed.", CQTalkLogConsole::TEXT_WHITE );

  42. break;

  43.  
  44. case gloox::ConnStreamClosed :

  45. m_pClient->OutputLogInfo( "The stream has been closed graciously.", CQTalkLogConsole::TEXT_WHITE );

  46. break;

  47.  
  48. case gloox::ConnIoError :

  49. m_pClient->OutputLogInfo( "An I/O error occured.", CQTalkLogConsole::TEXT_WHITE );

  50. break;

  51.  
  52. case gloox::ConnOutOfMemory :

  53. m_pClient->OutputLogInfo( "Out of memory. Uhoh.", CQTalkLogConsole::TEXT_WHITE );

  54. break;

  55.  
  56. case gloox::ConnNoSupportedAuth :

  57. m_pClient->OutputLogInfo( "The auth mechanisms the server offers are not supported" \

  58. "or the server offered no auth mechanisms at all.", CQTalkLogConsole::TEXT_WHITE );

  59. break;

  60.  
  61. case gloox::ConnTlsFailed :

  62. m_pClient->OutputLogInfo( "The server's certificate could not be verified.", CQTalkLogConsole::TEXT_WHITE );

  63. break;

  64.  
  65. case gloox::ConnAuthenticationFailed :

  66. m_pClient->OutputLogInfo( "Authentication failed. Username/password wrong or account does not exist.", CQTalkLogConsole::TEXT_WHITE );

  67. break;

  68.  
  69. case gloox::ConnUserDisconnected :

  70. m_pClient->OutputLogInfo( "The user (or higher-level protocol) requested a disconnect.", CQTalkLogConsole::TEXT_WHITE );

  71. break;

  72.  
  73. case gloox::ConnNotConnected :

  74. m_pClient->OutputLogInfo( "There is no active connection.", CQTalkLogConsole::TEXT_WHITE );

  75. break;

  76. }

  77. }

  78.  
  79. bool CQTalkConnectionListener::onTLSConnect( const CertInfo& info )

  80. {

  81. return true;

  82. }

 

现在我建立一个类CQTalkClient,用来沟通窗口和gloox的内部:

在该类中定义了一个函数用于连接服务器,以及完成gloox所有的注册

 
  1. BOOL CQTalkClient::Connect( CString strID, CString strJID, CString strPwd )

  2. {

  3. OutputLogInfo( "QTalk applictaion initailze successful !", CQTalkLogConsole::TEXT_WHITE );

  4.  
  5. ASSERT( ! strID.IsEmpty() );

  6. ASSERT( ! strJID.IsEmpty() );

  7. ASSERT( ! strPwd.IsEmpty() );

  8. if ( strID.IsEmpty() || strJID.IsEmpty() || strPwd.IsEmpty() )

  9. return FALSE;

  10.  
  11. setlocale( LC_ALL, "" );

  12.  
  13. const std::string jabberID = strJID.operator LPCTSTR();

  14. const std::string password = strPwd.operator LPCTSTR();

  15.  
  16. gloox::JID jid( jabberID);

  17.  
  18. jid.setResource("QTalk");

  19.  
  20. <span style="white-space:pre"> </span> m_pJabberClient = new gloox::Client( jid, password );

  21.  
  22. ASSERT( m_pJabberClient != NULL );

  23. if ( m_pJabberClient == NULL )

  24. return FALSE;

  25.  
  26. m_pQTalkDiscoHandler = new CQTalkDiscoHandler ();

  27. /*下面得到好友列表相关类指针*/

  28. <span style="white-space:pre"> </span>m_pQTalkRosterListener = new CQTalkRosterListener ( this );

  29. <span style="white-space:pre"> </span>/*下面得到Log相关类指针*/

  30. <span style="white-space:pre"> </span>m_pQTalkLogHandler = new CQTalkLogHandler ( this );

  31. <span style="white-space:pre"> </span>/*下面得到会话相关类指针*/

  32. m_pQTalkSessionHandler = new CQTalkSessionHandler ( this );

  33. /*下面得到连接相关类指针*/

  34. m_pQTalkConnectListener = new CQTalkConnectionListener( this );

  35. /*下面得到聊天室相关类指针*/

  36. m_pQTalkRoom = new QtalkMucRoom (this);

  37.  
  38.  
  39. /*下面得到文件传输相关类指针*/

  40. m_pQTalkIBBHandler = new CQTalkIBBHandler ( this );

  41.  
  42.  
  43. ASSERT( m_pQTalkDiscoHandler != NULL );

  44. ASSERT( m_pQTalkRosterListener != NULL );

  45. ASSERT( m_pQTalkLogHandler != NULL );

  46. ASSERT( m_pQTalkSessionHandler != NULL );

  47. ASSERT( m_pQTalkConnectListener != NULL );

  48. ASSERT( m_pQTalkIBBHandler != NULL );

  49.  
  50. //m_pJabberClient->setPresence( PresenceAvailable );

  51. <span style="white-space:pre"> </span>// m_pJabberClient->setInitialPriority( 4 );

  52. /*注册连接状态监听器,当调用该方法后, gloox 会在后台自动调用该接口实现中的相应方法。 */

  53. m_pJabberClient->registerConnectionListener( m_pQTalkConnectListener );

  54. /*注册好友列表监听器*/

  55. m_pJabberClient->rosterManager()->registerRosterListener( m_pQTalkRosterListener );

  56. m_pJabberClient->disco()->setVersion( "QTalk", GLOOX_VERSION ,"Windows");

  57. m_pJabberClient->disco()->setIdentity( "client", "Qtalk" );

  58. /*注册log监听器*/

  59. m_pJabberClient->logInstance().registerLogHandler( LogLevelDebug, LogAreaAll, m_pQTalkLogHandler );

  60. /*注册聊天室监听器*/

  61. m_pJabberClient->registerMUCInvitationHandler( m_pQTalkRoom );

  62. /*注册会话消息监听器*/

  63. m_pJabberClient->registerMessageSessionHandler(m_pQTalkSessionHandler);

  64.  
  65.  
  66. if ( m_pJabberClient->connect( false ) == false )

  67. {

  68. ReleaseRes();

  69. return FALSE;

  70. }

  71. <span style="white-space:pre"> </span>/*戏码得到名片相关类的指针*/

  72. m_pQTalkVCard = new VCardTest(this);

  73.  
  74. /*下面得到文件管理相关类指针*/

  75. m_pIBBManager = new gloox::InBandBytestreamManager( m_pJabberClient, m_pJabberClient->disco() );

  76. /*注册文件传输的监听器*/

  77. m_pIBBManager->registerInBandBytestreamHandler( m_pQTalkIBBHandler );

  78.  
  79. m_jid = jabberID;

  80. AfxGetMainWnd()->SetWindowText( m_jid.c_str() );

  81.  
  82. /*下面是一个线程,该线程用于接收发过来的信息和数据*/

  83. m_pQTalkThread = AfxBeginThread( QTalkMsgHandlerProc, this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED );

  84. ASSERT_VALID( m_pQTalkThread );

  85. if ( ! m_pQTalkThread )

  86. return FALSE;

  87.  
  88. m_pQTalkThread->ResumeThread();

  89.  
  90. OutputLogInfo( "Connect server successful !", CQTalkLogConsole::TEXT_WHITE );

  91.  
  92. return TRUE;

  93. }

  94.  
  95.  
  96. 线程函数的实现:

  97. UINT CQTalkClient::QTalkMsgHandlerProc( LPVOID lParam )

  98. {

  99. CQTalkClient* pQTalkClient = static_cast< CQTalkClient* >( lParam );

  100. ASSERT( pQTalkClient != NULL );

  101. if ( pQTalkClient == NULL )

  102. return 1;

  103.  
  104. pQTalkClient->OutputLogInfo( "Start LISTENER thread !", CQTalkLogConsole::TEXT_RED );

  105.  
  106. ASSERT( pQTalkClient->m_pQTalkDiscoHandler != NULL );

  107. ASSERT( pQTalkClient->m_pQTalkLogHandler != NULL );

  108. ASSERT( pQTalkClient->m_pQTalkSessionHandler != NULL );

  109. ASSERT( pQTalkClient->m_pQTalkConnectListener != NULL );

  110. ASSERT( pQTalkClient->m_pJabberClient != NULL );

  111.  
  112. gloox::ConnectionError ce = gloox::ConnNoError;

  113.  
  114. while ( TRUE )

  115. {

  116. DWORD dwFlag = ::WaitForSingleObject( CQTalkClient::s_QTalkEvent.m_hObject, 0 );

  117. if ( dwFlag == WAIT_OBJECT_0 )

  118. {

  119. pQTalkClient->OutputLogInfo( "End LISTENER thread !", CQTalkLogConsole::TEXT_RED );

  120. break;

  121. }

  122. ce = pQTalkClient->m_pJabberClient->recv();

  123. }

  124.  
  125. return 0;

  126. }

 

修改用户登录密码

在CQTalkClient函数中添加一个函数用于修改密码

 

 
  1. VOID CQTalkClient::SetPassword(CString password)

  2. {

  3. const std::string pwd = password.operator LPCTSTR();

  4. rr = new RegTest(TRUE);

  5. //rr->changepassword(serverName,useName,password);

  6. Registration *m_reg = new Registration(m_pJabberClient);

  7. m_reg->registerRegistrationHandler(rr);

  8. m_reg->changePassword( m_pJabberClient->username(), password.operator LPCTSTR() );

  9. ::MessageBox(NULL,"修改密码成功!",NULL,0);

  10. delete (m_reg);

  11. }


修改个人资料

 

 
  1. #include "./src/client.h"

  2. #include "./src/connectionlistener.h"

  3. #include "./src/disco.h"

  4. #include "./src/stanza.h"

  5. #include "./src/gloox.h"

  6. #include "./src/loghandler.h"

  7. #include "./src/vcardhandler.h"

  8. #include "./src/vcardmanager.h"

  9. #include "./src/vcard.h"

  10. using namespace gloox;

  11.  
  12. #include <stdio.h>

  13. #include <locale.h>

  14. #include <string>

  15.  
  16.  
  17. class CQTalkClient;

  18.  
  19. struct vcard_info

  20. {

  21. std::string username;

  22. std::string servername;

  23. std::string nickname;

  24. // std::list<VCard::Address> AddressList;

  25. std::string street;

  26. std::string family;

  27. std::string given;

  28. std::string middle;

  29. };

  30.  
  31. class VCardTest: public VCardHandler/*,ConnectionListener*/

  32. {

  33. public:

  34. VCardTest(void);

  35. VCardTest(CQTalkClient* pClient);

  36.  
  37. ~VCardTest(void);

  38.  
  39. public:

  40. void start(CString m_strjid);

  41.  
  42. void store(CString &,CString &,CString &);

  43.  
  44. //virtual void onConnect();

  45. //virtual void onDisconnect( ConnectionError e ) ;

  46. //virtual bool onTLSConnect( const CertInfo& info );

  47. //virtual void handleDiscoInfoResult( Stanza */*stanza*/, int /*context*/ );

  48. //virtual void handleDiscoItemsResult( Stanza */*stanza*/, int /*context*/ );

  49. virtual void handleDiscoError( Stanza */*stanza*/, int /*context*/ );

  50. //virtual void handleLog( LogLevel level, LogArea area, const std::string& message );

  51. virtual void handleVCard( const JID& jid, VCard *vcard);

  52. virtual void handleVCardResult(VCardContext context, const JID& jid,StanzaError se = StanzaErrorUndefined );

  53.  
  54. //Client *j;

  55. VCardManager *m_vManager;

  56. int m_count;

  57. CString strJID;

  58. public:

  59. struct vcard_info *str;

  60. // static CString m_strFetch;

  61. CString m_strSet;

  62. // AddressList& m_addressList;

  63. BOOL m_choice;

  64. private:

  65. CQTalkClient* m_pClient;

  66. };

 

 
  1. VCardTest::VCardTest(void)

  2. {

  3.  
  4. // m_pClient = NULL;

  5. }

  6.  
  7. VCardTest::VCardTest(CQTalkClient* pClient)

  8. {

  9. // m_count = 0;

  10. str = NULL;

  11. strJID.Empty();

  12. m_pClient = pClient;

  13. m_choice = TRUE;

  14. m_vManager = new VCardManager( m_pClient->GetClient());

  15. }

  16.  
  17. VCardTest::~VCardTest(void)

  18. {

  19. delete(m_vManager);

  20. }

  21.  
  22.  
  23. void VCardTest::start(CString m_strjid)

  24. {

  25. strJID = m_strjid;

  26. std::string strjid = m_strjid.operator LPCTSTR();

  27. JID jid( strjid );

  28. m_vManager->fetchVCard( strjid, this );

  29. }

  30.  
  31. void VCardTest::store(CString &nickname,CString &servername,CString &street)

  32. {

  33. std::string m_strjid = strJID.operator LPCTSTR();

  34. JID jid(m_strjid);

  35.  
  36. VCard *v = new VCard();

  37. v->setFormattedname( "Hurk the Hurk" );

  38. v->setNickname( nickname.operator LPCTSTR());

  39. v->setName( "Simpson", "Bart", "", "Mr.", "jr." );

  40. v->addAddress( "pobox", "app. 2", (street.operator LPCTSTR()), "Springfield", "region", "123", "USA", VCard::AddrTypeHome );

  41. m_vManager->storeVCard( v, this );

  42. m_vManager->fetchVCard( m_strjid, this );

  43. }

  44.  
  45. void VCardTest::handleVCard( const JID& jid, VCard *vcard )

  46. {

  47.  
  48.  
  49. std::string m_strjid = strJID.operator LPCTSTR();

  50. // ++m_count;

  51. if( !vcard )

  52. {

  53. printf( "empty vcard!\n" );

  54. return;

  55. }

  56. printf( "received vcard for %s: %s\n", jid.full().c_str(), vcard->tag()->xml().c_str());

  57. // ::AfxMessageBox(jid.full().c_str());

  58. // ::AfxMessageBox(vcard->tag()->xml().c_str());

  59.  
  60. // m_vManager->fetchVCard( jid, this );

  61. str = new vcard_info;

  62. str ->username = jid.username().c_str();

  63. str ->servername = jid.server().c_str();

  64. str ->nickname = vcard->nickname().c_str();

  65.  
  66. str->family = vcard->name().family;

  67. str->given = vcard->name().given;

  68. str->middle = vcard->name().middle;

  69.  
  70. VCard::AddressList::const_iterator it = vcard->addresses().begin();

  71. for( ; it != vcard->addresses().end(); ++it )

  72. {

  73. // printf( "address: %s\n", (*it).street.c_str() );

  74. str ->street = (*it).street.c_str();

  75. }

  76.  
  77. AfxGetMainWnd()->SendMessage( \

  78. QTalkGlobal::WM_QTALK_VCARD, \

  79. NULL, \

  80. (LPARAM)str );

  81. delete(str);

  82.  
  83. }

  84.  
  85. void VCardTest::handleVCardResult( VCardContext context, const JID& jid,StanzaError se)

  86. {

  87. //se = StanzaErrorUndefined;

  88. //printf( "vcard result: context: %d, jid: %s, error: %d\n", context, jid.full().c_str(), se );

  89. // m_vManager->fetchVCard( jid, this );

  90. }

 

然后只需在CQTalkClient中添加一个函数:

 

 
  1. VOID CQTalkClient::VCard(CString m_strjid/*,CString m_strPwd*/)

  2. {

  3. m_pQTalkVCard->start(m_strjid);

  4. }

 

 

添加联系人

在CQTalkClient中添加函数

 

 
  1. VOID CQTalkClient::AddConnecter(CString m_jid,CString m_group)

  2. {

  3. m_cf = TRUE;

  4. m_delete = FALSE;

  5. const std::string m_strjid = m_jid.operator LPCTSTR();

  6. m_strGroup = m_group;

  7. JID jid(m_strjid);

  8. m_pJabberClient->rosterManager()->subscribe(jid);

  9. }

 

关于添加联系人的类:

 

 
  1. #include "./src/rosterlistener.h"

  2. #include "./src/rostermanager.h"

  3.  
  4. class CQTalkClient;

  5.  
  6. using namespace gloox;

  7.  
  8. class CQTalkRosterListener : public gloox::RosterListener

  9. {

  10. // Construction

  11. public:

  12. CQTalkRosterListener();

  13.  
  14. CQTalkRosterListener( CQTalkClient* pClient);

  15.  
  16. virtual ~CQTalkRosterListener();

  17.  
  18. // Implementation

  19. private:

  20. virtual void handleItemSubscribed ( const JID& jid );

  21.  
  22. virtual void handleItemUnsubscribed( const JID& jid);

  23.  
  24. virtual void handleItemAdded ( const JID& jid );

  25.  
  26. virtual void handleItemRemoved( const JID& jid );

  27.  
  28. virtual void handleItemUpdated( const JID& jid );

  29.  
  30. virtual void handleRoster( const Roster& roster );

  31.  
  32. virtual void handleRosterPresence( const RosterItem& item, const std::string& resource,Presence presence, const std::string& msg );

  33.  
  34. virtual bool handleSubscriptionRequest ( const JID& jid, const std::string& msg );

  35.  
  36. virtual bool handleUnsubscriptionRequest( const JID& jid, const std::string& msg );

  37.  
  38. virtual void handleRosterError( Stanza* stanza );

  39.  
  40. virtual void handleNonrosterPresence( Stanza* stanza );

  41.  
  42. virtual void handleSelfPresence( const RosterItem& item, const std::string& resource,Presence presence, const std::string& msg );

  43.  
  44.  
  45.  
  46. // Implementation

  47. private:

  48. CQTalkClient* m_pClient;

  49. };

 

 
  1. CQTalkRosterListener::CQTalkRosterListener()

  2. {

  3. m_pClient = NULL;

  4. }

  5.  
  6. CQTalkRosterListener::CQTalkRosterListener(CQTalkClient* pClient )

  7. {

  8. m_pClient=pClient;

  9. }

  10.  
  11. CQTalkRosterListener::~CQTalkRosterListener()

  12. {

  13. }

  14.  
  15. /

  16. // CQTalkRosterListener method implementation

  17.  
  18. void CQTalkRosterListener::handleItemSubscribed( const JID& jid )

  19. {

  20. m_pClient->OutputLogInfo( "RosterListener::itemSubscribed", CQTalkLogConsole::TEXT_WHITE );

  21. AfxGetMainWnd()->PostMessage( \

  22. QTalkGlobal::WM_QTALK_MESSAGE, \

  23. QTalkGlobal::WM_QTALK_ROSTER, \

  24. QTalkGlobal::ROSTER_LIST_ALL );

  25. // m_pClient->m_cf = FALSE;

  26. }

  27.  
  28. void CQTalkRosterListener::handleItemUnsubscribed(const JID& jid)

  29. {

  30.  
  31. }

  32.  
  33. void CQTalkRosterListener::handleItemAdded( const JID& jid )

  34. {

  35. m_pClient->OutputLogInfo( "RosterListener::itemAdded", CQTalkLogConsole::TEXT_WHITE );

  36.  
  37. RosterItem* rostitem = m_pClient->GetClient()->rosterManager()->getRosterItem(jid);

  38. QTalkGlobal::ROSTER rosterItem;

  39. rosterItem.jid = rostitem->jid();

  40. rosterItem.name = rostitem->name();

  41. rosterItem.subsciption = rostitem->subscription();

  42. rosterItem.groups.push_back((m_pClient->m_strGroup).operator LPCTSTR());

  43. m_pClient->m_rosterList.push_back( rosterItem );

  44.  
  45. StringList g;

  46. g.push_back((m_pClient->m_strGroup).operator LPCTSTR());

  47.  
  48. m_pClient->GetClient()->rosterManager()->add(jid,rostitem->name(),g);

  49. }

  50.  
  51. void CQTalkRosterListener::handleItemRemoved(const JID& jid )

  52. {

  53. m_pClient->OutputLogInfo( "RosterListener::itemRemoved", CQTalkLogConsole::TEXT_WHITE );

  54. if(m_pClient->m_delete)

  55. {

  56. QTalkGlobal::CIT_ROSTER_LIST i;

  57. i = m_pClient->m_rosterList.begin();

  58. while(i != m_pClient->m_rosterList.end())

  59. {

  60. QTalkGlobal::ROSTER rosterItem = *i;

  61. if(rosterItem.jid == jid.full())

  62. {

  63. m_pClient->m_rosterList.erase(i++);

  64. }

  65. else

  66. {

  67. i++;

  68. }

  69. }

  70.  
  71. AfxGetMainWnd()->SendMessage( \

  72. QTalkGlobal::WM_QTALK_MESSAGE, \

  73. QTalkGlobal::WM_QTALK_ROSTER, \

  74. QTalkGlobal::ROSTER_DELETE_ITEM );

  75. }

  76. }

  77.  
  78. void CQTalkRosterListener::handleItemUpdated( const JID& jid)

  79. {

  80. m_pClient->OutputLogInfo( "RosterListener::itemUpdated", CQTalkLogConsole::TEXT_WHITE );

  81.  
  82. if(!m_pClient->m_cf)

  83. {

  84. AfxGetMainWnd()->PostMessage( \

  85. QTalkGlobal::WM_QTALK_MESSAGE, \

  86. QTalkGlobal::WM_QTALK_ROSTER, \

  87. QTalkGlobal::ROSTER_LIST_ALL );

  88. // m_pClient->m_cf = TRUE;

  89. }

  90. }

  91.  
  92.  
  93.  
  94. // By calling this method

  95. // you can get all roster from the server

  96.  
  97. void CQTalkRosterListener::handleRoster( const Roster& roster )

  98. {

  99. m_pClient->OutputLogInfo( "Manager the roster !", CQTalkLogConsole::TEXT_WHITE );

  100.  
  101. Roster::const_iterator it = roster.begin();

  102.  
  103. m_pClient->m_rosterList.clear();

  104. QTalkGlobal::ROSTER rosterItem;

  105.  
  106. for ( ; it != roster.end(); it++ )

  107. {

  108. m_pClient->OutputLogInfo((*it).second->jid().c_str(),CQTalkLogConsole::TEXT_PURPLE );

  109. m_pClient->OutputLogInfo((*it).second->name().c_str(), CQTalkLogConsole::TEXT_PURPLE );

  110. //m_pClient->OutputLogInfo((*it).second->subscription(), CQTalkLogConsole::TEXT_PURPLE );

  111.  
  112. StringList g = (*it).second->groups();

  113. StringList::const_iterator it_g = g.begin();

  114. for( ; it_g != g.end(); ++it_g )

  115. {

  116. std::string msg;

  117. CCodeLib::UTF8ToGB2312( msg, ( *it_g ).c_str(), ( *it_g ).length() );

  118. m_pClient->OutputLogInfo( msg.c_str(), CQTalkLogConsole::TEXT_YELLOW );

  119. }

  120.  
  121. rosterItem.jid = ( *it ).second->jid();

  122. rosterItem.name = ( *it ).second->name();

  123. rosterItem.subsciption = ( *it ).second->subscription();

  124. rosterItem.groups = ( *it ).second->groups();

  125. rosterItem.presence = 6;

  126. m_pClient->m_rosterList.push_back( rosterItem );

  127.  
  128. }

  129.  
  130. AfxGetMainWnd()->PostMessage( \

  131. QTalkGlobal::WM_QTALK_MESSAGE, \

  132. QTalkGlobal::WM_QTALK_ROSTER, \

  133. QTalkGlobal::ROSTER_LIST_ALL );

  134. }

  135.  
  136. // The rosters are not online or online

  137. // calling these method to implement roster update...

  138.  
  139. void CQTalkRosterListener::handleRosterPresence( const RosterItem& item,const std::string& resource,Presence presence, const std::string& msg )

  140. {

  141. m_pClient->OutputLogInfo( "RosterListener::presenceUpdated", CQTalkLogConsole::TEXT_WHITE );

  142. QTalkGlobal::CIT_ROSTER_LIST cit = m_pClient->m_rosterList.begin();

  143. for(;cit != m_pClient->m_rosterList.end(); cit++)

  144. {

  145. if(cit->jid == item.jid())

  146. {

  147. cit->presence = presence;

  148. }

  149. }

  150.  
  151. AfxGetMainWnd()->SendMessage( \

  152. QTalkGlobal::WM_QTALK_MESSAGE, \

  153. QTalkGlobal::WM_QTALK_ROSTER, \

  154. QTalkGlobal::ROSTER_PRESENCEUPDATE );

  155. }

  156.  
  157. bool CQTalkRosterListener::handleSubscriptionRequest( const JID& jid, const std::string& msg )

  158. {

  159. m_pClient->OutputLogInfo( "RosterListener::subscriptionRequest", CQTalkLogConsole::TEXT_WHITE );

  160. // m_pClient->m_cf = FALSE;

  161. if(!m_pClient->m_cf)

  162. {

  163. AfxGetMainWnd()->SendMessage( \

  164. QTalkGlobal::WM_QTALK_MESSAGE, \

  165. QTalkGlobal::WM_QTALK_ROSTER, \

  166. QTalkGlobal::ROSTER_SUBSCRIPTIONREQUEST);

  167. }

  168.  
  169. if(!m_pClient->m_choice)

  170. {

  171. m_pClient->GetClient()->rosterManager()->unsubscribe(jid);

  172. }

  173.  
  174. m_pClient->m_cf = FALSE;

  175.  
  176. return true;

  177. }

  178.  
  179. bool CQTalkRosterListener::handleUnsubscriptionRequest( const JID& jid, const std::string& msg )

  180. {

  181. m_pClient->OutputLogInfo( "RosterListener::unsubscriptionRequest", CQTalkLogConsole::TEXT_WHITE );

  182. return true;

  183. }

  184.  
  185. void CQTalkRosterListener::handleRosterError( Stanza* stanza )

  186. {

  187.  
  188. }

  189.  
  190. void CQTalkRosterListener::handleNonrosterPresence( Stanza* stanza )

  191. {

  192.  
  193. }

  194.  
  195. void CQTalkRosterListener::handleSelfPresence( const RosterItem& item, const std::string& resource,Presence presence, const std::string& msg )

  196. {

  197.  
  198. }


聊天室:

 

 

 
  1. #include "./src/client.h"

  2. #include "./src/connectionlistener.h"

  3. #include "./src/mucroomhandler.h"

  4. #include "./src/mucroom.h"

  5. #include "./src/disco.h"

  6. #include "./src/stanza.h"

  7. #include "./src/dataform.h"

  8. #include "./src/gloox.h"

  9. #include "./src/lastactivity.h"

  10. #include "./src/loghandler.h"

  11. #include "./src/logsink.h"

  12. #include "./src/mucinvitationhandler.h"

  13.  
  14. using namespace gloox;

  15.  
  16. #include <stdio.h>

  17. #include <locale.h>

  18. #include <string>

  19.  
  20. #ifdef WIN32

  21. #include <windows.h>

  22. #endif

  23.  
  24. class CQTalkClient;

  25.  
  26. class QTalkMucRoom : public MUCRoomHandler,public gloox::MUCInvitationHandler

  27. {

  28. public:

  29. QTalkMucRoom();

  30. QTalkMucRoom( CQTalkClient* pClient);

  31. ~QTalkMucRoom();

  32. public:

  33. void start(CString roomName);

  34. void ToRoom(CString str,CString msg);

  35. void OnChatSession( std::string nick, std::string message );

  36. void SendToRoom(CString message);

  37. void ServerRoom();

  38.  
  39. private:

  40. virtual void handleMUCParticipantPresence( MUCRoom * /*room*/, const MUCRoomParticipant participant,

  41. Presence presence );

  42. virtual void handleMUCMessage( MUCRoom* /*room*/, const std::string& nick, const std::string& message,

  43. bool history, const std::string& /*when*/, bool priv );

  44. virtual void handleMUCSubject( MUCRoom * /*room*/, const std::string& nick, const std::string& subject );

  45. virtual void handleMUCError( MUCRoom * /*room*/, StanzaError error );

  46. virtual void handleMUCInfo( MUCRoom * /*room*/, int features, const std::string& name,

  47. const DataForm *infoForm );

  48. virtual void handleMUCItems( MUCRoom * /*room*/, const StringMap& items );

  49. virtual void handleMUCInviteDecline( MUCRoom * /*room*/, const JID& invitee, const std::string& reason );

  50. virtual bool handleMUCRoomCreation( MUCRoom *room );

  51. virtual void handleMUCInvitation( const JID& room, const JID& invitee, const std::string& reason,

  52. const std::string& body, const std::string& password,

  53. bool cont );

  54. private:

  55. MUCRoom *m_room;

  56. MUCRoom *m_serverRoom;

  57. CQTalkClient* m_pClient;

  58. BOOL m_send;

  59. BOOL m_server;

  60. };

 

 
  1. #include "StdAfx.h"

  2. #include "QTalkMucRoom.h"

  3. #include "QTalkClient.h"

  4.  
  5. QTalkMucRoom::QTalkMucRoom()

  6. {

  7.  
  8. // m_pClient = NULL;

  9. }

  10.  
  11. QTalkMucRoom::QTalkMucRoom(CQTalkClient* pClient)

  12. {

  13. m_room = NULL;

  14. m_serverRoom = NULL;

  15. m_pClient = pClient;

  16. m_send = TRUE;

  17. m_server = TRUE;

  18. }

  19.  
  20. QTalkMucRoom::~QTalkMucRoom()

  21. {

  22. delete( m_room );

  23. delete( m_serverRoom);

  24. }

  25.  
  26. void QTalkMucRoom::start(CString roomName)

  27. {

  28. const std::string strjid = roomName.operator LPCTSTR();

  29. m_server = TRUE;

  30.  
  31. JID nick(strjid);

  32. m_room = new MUCRoom( m_pClient->GetClient(), nick, this, 0 );

  33. m_room->join();

  34. m_room->getRoomInfo();

  35. m_room->getRoomItems();

  36. // delete(m_room);

  37. }

  38.  
  39. void QTalkMucRoom::ServerRoom()

  40. {

  41. m_server = FALSE;

  42. JID nick("conference.upower-a448cf28");

  43. m_serverRoom = new MUCRoom( m_pClient->GetClient(), nick, this, 0);

  44. m_serverRoom->getRoomItems();

  45. // delete( m_room );

  46. }

  47.  
  48. void QTalkMucRoom::ToRoom(CString str,CString msg)

  49. {

  50. const std::string strjid = str.operator LPCTSTR();

  51. JID jid(strjid);

  52.  
  53. m_room->invite(jid,msg.operator LPCTSTR());

  54. }

  55.  
  56. void QTalkMucRoom::SendToRoom(CString message)

  57. {

  58. m_send = FALSE;

  59. const std::string strMessage = message.operator LPCTSTR();

  60. m_room->send(strMessage);

  61. }

  62.  
  63. void QTalkMucRoom::handleMUCParticipantPresence( MUCRoom * /*room*/, const MUCRoomParticipant participant,

  64. Presence presence )

  65. {

  66. std::string str = m_pClient->GetJID();

  67. if( presence == PresenceAvailable )

  68. {

  69. // printf( "!!!!!!!!!!!!!!!! %s is in the room, too\n", participant.nick->resource().c_str() );

  70. if(str.compare(participant.jid->bare()))

  71. {

  72. AfxGetMainWnd()->PostMessage( \

  73. QTalkGlobal::WM_QTALK_CONNECT, \

  74. QTalkGlobal::CONECT_PRESENCE_AVAILABLE, \

  75. NULL);

  76. }

  77. }

  78.  
  79. else if( presence == PresenceUnavailable )

  80. printf( "!!!!!!!!!!!!!!!! %s left the room\n", participant.nick->resource().c_str() );

  81. else

  82. printf( "Presence is %d of %s\n", presence, participant.nick->resource().c_str() );

  83. }

  84.  
  85. void QTalkMucRoom::handleMUCMessage( MUCRoom* /*room*/, const std::string& nick, const std::string& message,

  86. bool history, const std::string& /*when*/, bool priv )

  87. {

  88. //printf( "%s said: '%s' (history: %s, private: %s)\n", nick.c_str(), message.c_str(),

  89. // history ? "yes" : "no", priv ? "yes" : "no" );

  90. if(m_send)

  91. {

  92. OnChatSession(nick,message);

  93. }

  94. m_send = TRUE;

  95. }

  96.  
  97. void QTalkMucRoom::handleMUCSubject( MUCRoom * /*room*/, const std::string& nick, const std::string& subject )

  98. {

  99. if( nick.empty() )

  100. printf( "Subject: %s\n", subject.c_str() );

  101. else

  102. printf( "%s has set the subject to: '%s'\n", nick.c_str(), subject.c_str() );

  103. }

  104.  
  105. void QTalkMucRoom::handleMUCError( MUCRoom * /*room*/, StanzaError error )

  106. {

  107. printf( "!!!!!!!!got an error: %d", error );

  108. }

  109.  
  110. void QTalkMucRoom::handleMUCInfo( MUCRoom * /*room*/, int features, const std::string& name,

  111. const DataForm *infoForm )

  112. {

  113. // printf( "features: %d, name: %s, form xml: %s\n", features, name.c_str(), infoForm->tag()->xml().c_str() );

  114. }

  115.  
  116. void QTalkMucRoom::handleMUCItems( MUCRoom * /*room*/, const StringMap& items )

  117. {

  118. StringMap::const_iterator it = items.begin();

  119. for( ; it != items.end(); ++it )

  120. {

  121. // printf( "%s -- %s is an item here\n", (*it).first.c_str(), (*it).second.c_str() );

  122. m_pClient->m_serverRoomList.push_back((*it).first);

  123. }

  124. if(!m_server)

  125. {

  126. AfxGetMainWnd()->PostMessage( \

  127. QTalkGlobal::WM_QTALK_CHATROOM, \

  128. QTalkGlobal::WM_QTALK_SERVERCHATROOMLIST, \

  129. QTalkGlobal::SERVERCHATROOM_LIST);

  130. }

  131. }

  132.  
  133. void QTalkMucRoom::handleMUCInviteDecline( MUCRoom * /*room*/, const JID& invitee, const std::string& reason )

  134. {

  135. printf( "Invitee %s declined invitation. reason given: %s\n", invitee.full().c_str(), reason.c_str() );

  136. }

  137.  
  138. bool QTalkMucRoom::handleMUCRoomCreation( MUCRoom *room )

  139. {

  140. // printf( "room %s didn't exist, beeing created.\n", room->name().c_str() );

  141. return true;

  142. }

  143.  
  144.  
  145. void QTalkMucRoom::handleMUCInvitation( const JID& room, const JID& invitee, const std::string& reason,

  146. const std::string& body, const std::string& password,

  147. bool cont )

  148. {

  149. // int i = 0;

  150. const std::string strUsr = room.username();

  151. const std::string strInvitee = room.username();

  152. CString str = _T("");

  153. str.Format("%s@conference.upower-a448cf28/%s",strUsr.c_str(),strInvitee.c_str());

  154. JID nick(str.operator LPCTSTR());

  155.  
  156.  
  157.  
  158. MUCRoom* m_serverRoom1 = new MUCRoom( m_pClient->GetClient(), nick, this, 0);

  159. m_room->join();

  160. // m_room = new MUCRoom( m_pClient->GetClient(), room, this, 0);

  161. //m_room->join();

  162. //JID jid("test@upower-a448cf28");

  163. //m_pClient->GetClient()->registerPresenceHandler(jid,this);

  164. }

  165.  
  166. void QTalkMucRoom::OnChatSession( std::string nick, std::string message )

  167. {

  168. m_pClient->m_nick = nick;

  169. m_pClient->m_rMessage = message;

  170. AfxGetMainWnd()->SendMessage(\

  171. QTalkGlobal::WM_QTALK_CHATROOM, \

  172. QTalkGlobal::WM_QTALK_ROOMSESSION, \

  173. QTalkGlobal::CHATROOM_MSG

  174. );

  175. }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值