利用asmack实现Openfire的C++客户端

在openfire的官网上,有支持Java语言的asmack,也有支持C#语言的XMPP,但是有些应用场景可能需要C++语言作为openfire的客户端。本篇文章主要介绍如何利用asmack来实现C++语言编写的客户端。(需要有一定的jni基础)

第一步:利用Java语言和asmack可以完美的和openfire进行通讯(消息的收发),那么可以将Java平台下的该工程打包成jar包;

用eclipse打包时,由于项目里面含有多个第三方jar包,需要注意的是在src平级目录下新建MANIFEST.MF文件,文件内容如下:

Manifest-Version: 1.0
Class-Path: lib/asmack-jse-buddycloud-2010.12.11.jar lib/kxml2-2.2.2.jar lib/xmlpull_1_0_5.jar
Main-Class: com.uuorange.example.MainScene
注意:冒号后面都有空格,两个jar包之间也有空格,最后需要空一行,打包过程不在详细介绍

    打包的jar包和放在lib目录下引入的第三方jar包,在使用时,需要放在同一目录下

第二步:C++调用Java的jar包以及jar包里面的函数;

在win32的Visual studio 2008上进行环境配置和编码实现(反键项目 属性->配置属性->C/C++->常规->附加包含目录:

"...../java/jdk/include/win32","...../java/jdk/include")

关键代码:

#include "stdafx.h"
#include "jni.h"
#include <Windows.h>

bool startJVM();

int _tmain(int argc, _TCHAR* argv[])
{
	startJVM();
	return 0;
}

typedef jint(JNICALL *JNICREATEPROC)(JavaVM **, void **, void *);
//设置输出流
bool setStream(JNIEnv *env, const char* fileName, const char* method);

//启动java虚拟机

bool startJVM(){
	//获取jvm动态库的路径
	TCHAR* jvmPath = _T("C://Program Files//Java//jdk1.8.0_65//jre//bin//client//jvm.dll");

	//java虚拟机启动时接收的参数,每个参数单独一项
	int nOptionCount = 2;
	JavaVMOption vmOption[2];
	//设置JVM最大允许分配的堆内存,按需分配
	vmOption[0].optionString = "-Xmx256M";
	//设置classpath
	vmOption[1].optionString = "-Djava.class.path=e:/FunCall_C2Java_Callee.jar";

	JavaVMInitArgs vmInitArgs;
	vmInitArgs.version = JNI_VERSION_1_6;
	vmInitArgs.options = vmOption;
	vmInitArgs.nOptions = nOptionCount;
	//忽略无法识别jvm的情况
	vmInitArgs.ignoreUnrecognized = JNI_TRUE;

	//设置启动类,注意分隔符为"/"
	const char startClass[] = "com/uuorange/example/MainScene";
	//启动方法,一般是main函数,当然可以设置成其他函数
	const char startMethod[] = "main";

	//加载JVM,注意需要传入的字符串为LPCWSTR,指向一个常量Unicode字符串的32位指针,相当于const wchar_t*
	HINSTANCE jvmDLL = LoadLibrary(jvmPath);
	if(jvmDLL == NULL){
		printf("加载JVM动态库错误");
		return false;
	}

	//初始化jvm物理地址
	JNICREATEPROC jvmProcAddress = (JNICREATEPROC)GetProcAddress(jvmDLL, "JNI_CreateJavaVM");
	if(jvmDLL == NULL){
		FreeLibrary(jvmDLL);
		printf("加载JVM动态库错误");
		return false;
	}

	//创建JVM
	JNIEnv *env;
	JavaVM *jvm;
	jint jvmProc = (jvmProcAddress)(&jvm, (void **)&env, &vmInitArgs);
	if(jvmProc < 0 || jvm == NULL ||env == NULL){
		FreeLibrary(jvmDLL);
		printf("创建JVM错误");
		return false;
	}else{
		printf("创建JVM成功\n");
	}

	//加载启动类
	jclass mainclass = env ->FindClass(startClass);
	if(env -> ExceptionCheck() == JNI_TRUE || mainclass == NULL){
		env -> ExceptionDescribe();
		env -> ExceptionClear();
		FreeLibrary(jvmDLL);
		printf("加载启动类错误");
		return false;
	}else{
		printf("加载启动类成功\n");
	}

	//jmethodID mid = env->GetStaticMethodID(mainclass, "fun", "()V");
	//env->CallStaticVoidMethod(mainclass, mid, 100);
	jobject obj = env->AllocObject(mainclass);

	//jmethodID mid1 = env->GetMethodID(mainclass, "call", "()Ljava/lang/String;");//Ljava/lang/String;Ljava/lang/String;I
	jmethodID mid1 = env->GetMethodID(mainclass, "call", "()V");
	jstring msg = (jstring)env->CallObjectMethod(obj, mid1);

                                                                                                                                                                                                     
	jstring to =  env->NewStringUTF("test2");
	jstring content =  env->NewStringUTF("hello, I am from C++");


	printf("开始睡觉\n");
	Sleep(10000);
	printf("继续执行\n");
	jmethodID mid2 = env->GetStaticMethodID(mainclass, "sendMessage", "(Ljava/lang/String;Ljava/lang/String;I)V");
	env->CallStaticVoidMethod(mainclass, mid2, to, content, 1);
	printf("加载启动类成功\n");
	//jvm释放
	jvm -> DestroyJavaVM();
	return true;
}

第三步:通过上面两步可以实现启动jvm、启动jar包、通过openfire给指定的客户端发送消息。C++客户端在接收消息时,只能在Java jar包里面接收到消息,没法通过回调传给上层的C++,为了达到Java jar包里面的数据能够传给C++,好像没有特别好的方法,如果某个大神有好方法,希望告知,谢谢了。本人为了实现该功能,在C++客户端上的C++层和Java层建立了一个TCP的长连接,这样Java收到的即时消息可以通过TCP传给上层的C++。

PS:最近在XMPP的官网上(https://xmpp.org/software/)发现了XMPP支持的各种语言的Clients、Servers和Libraries,包括对应的API文档都有(英语阅读能力要好)。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值