前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >NanoMsg框架|Android中简单封装PAIR的使用(附Demo地址)

NanoMsg框架|Android中简单封装PAIR的使用(附Demo地址)

作者头像
Vaccae
发布2020-02-27 15:26:42
8420
发布2020-02-27 15:26:42
举报
文章被收录于专栏:微卡智享微卡智享

本文长度为3287,预计阅读8分钟

前言

接着上一篇《NanoMsg框架|Android Studio编译NanoMsg源码》来说的,我们介绍了Nanomsg的几个常用的函数,以及一段简单的调用代码,这篇我们介绍一下在Android下使用PAIR模式的简单封装。

实现效果

封装思路

微卡智享

#

说明

1

通过JNI把几个核心函数进行处理

2

把每种模式新建一个类用于单独处理相关的通讯

首先我们新建了一个NanoMsgJNI的类,这个类主要就是调用NDK的NanaMsg相关的函数,就是把几个最终会用到的函数bind,socket,connect,send,recv都加入进来提供外部调用。

NanoMsgJNI

代码语言:javascript
复制
package dem.vac.androidnanomsg

/**
 * 作者:Vaccae
 * 功能模块说明:
 */

class NanoMsgJNI {
    companion object {
        // Used to load the 'native-lib' library on application startup.
        init {
            System.loadLibrary("ndknanomsg")
        }
    }

    //初始化Socket
    external fun init(ntype: String): Int

    //绑定地址
    external fun bind(connectsocket: Int, ipadr: String): Int

    //关闭套接了
    external fun close(connectsocket: Int): Int

    //连接数据库
    external fun connect(connectsocket: Int, ipadr: String): Int

    //发送数据
    external fun send(connectsocket: Int, sendmsg: String): Int

    //接收数据
    external fun recv(connectsocket: Int): String

}

对应的native-lib中我们写入对应的函数方法,不知道什么原因,这里定义方法没法用ALT+ENTER进行自动创建了,所以我们方法都是自己手写的,如下

方法的命名规则就是Java_包名_类名_方法名

native-lib.cpp

代码语言:javascript
复制
#include <jni.h>
#include <string>
#include <nn.h>
#include <stdio.h>
#include <protocol.h>
#include <pair.h>
#include <android/log.h>

// log标签
#define  TAG    "NanoErrInfo"
// 定义info信息
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__)
// 定义debug信息
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
// 定义error信息
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__)

//抛异常类标签
#define ERRCLS "java/lang/IllegalArgumentException"
//抛异常函数
void throwByName(JNIEnv *env, const char *name, const char *msg) {
    jclass cls = env->FindClass(name);
    if (cls != NULL) {
        //检测是否有异常发生
        if (0 != env->ExceptionOccurred()) {
            //清除异常堆栈
            env->ExceptionClear();
        }
        env->ThrowNew(cls, msg);
    }
    env->DeleteLocalRef(cls);
}

//获取NanoMsg连接类型
int getNanotype(const char *ntype) {
    if (strcmp(ntype, "PAIR") == 0) {
        return NN_PAIR;
    } else {
        return -1;
    }
}

extern "C" JNIEXPORT jint JNICALL
Java_dem_vac_androidnanomsg_NanoMsgJNI_init(
        JNIEnv *env,
        jobject,
        jstring ntype_
) {
    int initsocket = -1;

    //设置超时时间
    int timeo = 100;
    //获取连接方式
    const char *ntype = env->GetStringUTFChars(ntype_, 0);

    try {
        initsocket = nn_socket(AF_SP, getNanotype(ntype));
        if (initsocket < 0) {
            throw initsocket;
        }

        //设置超时
        nn_setsockopt(initsocket, 0, NN_SNDTIMEO, &timeo, sizeof(timeo));
        nn_setsockopt(initsocket, 0, NN_RCVTIMEO, &timeo, sizeof(timeo));
    }
    catch (int e) {
        char errmsg[100];
        sprintf(errmsg, "创建Socket连接失败,返回码:%d", e);
        LOGE("%s\n", errmsg);
        throwByName(env, ERRCLS, errmsg);
    }
    //释放资源
    env->ReleaseStringUTFChars(ntype_, ntype);
    return initsocket;
}

extern "C" JNIEXPORT jint JNICALL
Java_dem_vac_androidnanomsg_NanoMsgJNI_bind(
        JNIEnv *env,
        jobject,
        jint socketid_,
        jstring ipadr_
) {
    int bindsocket = -1;

    //获取地址
    const char *ipadress = env->GetStringUTFChars(ipadr_, 0);
    const char *ipadrpre = "tcp://";

    int len = strlen(ipadress) + strlen(ipadrpre);
    char ipstr[len];
    strcpy(ipstr, ipadrpre);
    strcat(ipstr, ipadress);


    try {
        //绑定地址
        bindsocket = nn_bind(socketid_, ipstr);
        if (bindsocket < 0) {
            throw bindsocket;
        }
    } catch (int e) {
        char errmsg[100];
        sprintf(errmsg, "绑定地址失败,返回码:%d", e);
        LOGE("%s\n", errmsg);
        throwByName(env, ERRCLS, errmsg);
    }
    //释放资源
    env->ReleaseStringUTFChars(ipadr_, ipadress);
    return bindsocket;
}

extern "C" JNIEXPORT jint JNICALL
Java_dem_vac_androidnanomsg_NanoMsgJNI_close(
        JNIEnv *env,
        jobject,
        jint socketid_
) {
    int closesocket = -1;
    try {
        //关闭套接字
        closesocket = nn_close(socketid_);
        if (closesocket != 1) {
            throw closesocket;
        }

    } catch (int e) {
        char errmsg[100];
        sprintf(errmsg, "关闭套接字失败,返回码:%d", e);
        LOGE("%s\n", errmsg);
        throwByName(env, ERRCLS, errmsg);
    }
    return closesocket;
}

extern "C" JNIEXPORT jint JNICALL
Java_dem_vac_androidnanomsg_NanoMsgJNI_connect(
        JNIEnv *env,
        jobject,
        jint socketid_,
        jstring ipadr_
) {
    int connectsocket = -1;

    //获取地址
    const char *ipadress = env->GetStringUTFChars(ipadr_, 0);
    const char *ipadrpre = "tcp://";

    int len = strlen(ipadress) + strlen(ipadrpre);
    char ipstr[len];
    strcpy(ipstr, ipadrpre);
    strcat(ipstr, ipadress);


    try {
        //连接服务器
        connectsocket = nn_connect(socketid_, ipstr);
        if (connectsocket < 0) {
            throw connectsocket;
        }
    } catch (int e) {
        char errmsg[100];
        sprintf(errmsg, "连接服务器失败,返回码:%d", e);
        LOGE("%s\n", errmsg);
        throwByName(env, ERRCLS, errmsg);
    }
    //释放资源
    env->ReleaseStringUTFChars(ipadr_, ipadress);
    return connectsocket;
}

extern "C" JNIEXPORT jint JNICALL
Java_dem_vac_androidnanomsg_NanoMsgJNI_send(
        JNIEnv *env,
        jobject,
        jint socketid_,
        jstring sendmsg_
) {
    int count = 0;

    //获取发送字符串
    const char *sendmsg = env->GetStringUTFChars(sendmsg_, 0);

    try {
        //计算发送字节长度
        int str_len = strlen(sendmsg);
        //发送数据
        count = nn_send(socketid_, sendmsg, static_cast<size_t>(str_len), 0);
        if (count < 0) {
            throw count;
        }
    } catch (int e) {
        char errmsg[100];
        sprintf(errmsg, "程序发送数据失败!返回码:%d", e);
        LOGE("%s\n", errmsg);
        throwByName(env, ERRCLS, errmsg);
    }
    //释放资源
    env->ReleaseStringUTFChars(sendmsg_, sendmsg);
    return count;
}

extern "C" JNIEXPORT jstring JNICALL
Java_dem_vac_androidnanomsg_NanoMsgJNI_recv(
        JNIEnv *env,
        jobject,
        jint socketid_
) {
    jstring recvmsg;
    try {
        int nbytes = 0;
        //定义一个空指针
        void *buf = NULL;
        //接收数据
        nbytes = nn_recv(socketid_, &buf, NN_MSG, 0);
        if (nbytes < 0) {
            throw nbytes;
        } else {
            recvmsg = env->NewStringUTF((char *) buf);
            nn_freemsg(buf);
        }

    } catch (int e) {
        char errmsg[100];
        sprintf(errmsg, "接收数据失败!返回码:%d", e);
        LOGE("%s\n", errmsg);
        throwByName(env, ERRCLS, errmsg);
        recvmsg = env->NewStringUTF("");
    }
    return recvmsg;
}

注意一下getNanotype这个方法,这里我们是在init主函数中传入的字符串,用于判断现在是什么模式的,我这里因为只做的PAIR,所以只写了这一个模式,后面的可以自己加入。

面两个其实就是把我们通过JNI调用NanoMsg的都已经简单的做好了,下一步我们就可以根据这里设置好的进行PAIR的操作了,

PAIR的封装

微卡智享

新建一个NNPAIR的类,主要就是保留当我们初始化后返回的套接字,所以定义了一个pairsocket,后面的操作都是根据传入这个套接字进行处理的。

NNPAIR

代码语言:javascript
复制
package dem.vac.androidnanomsg

/**
 * 作者:Vaccae
 * 功能模块说明:
 */
class NNPAIR {
    private var nnjni:NanoMsgJNI = NanoMsgJNI()
    private var pairsocket: Int = -1

   init {
       if (pairsocket == -1) {
           pairsocket = nnjni.init("PAIR")
       }
   }

    //PAIR连接
    fun connect(ipadr: String): Boolean {
        val res = nnjni.connect(pairsocket, ipadr)
        return res >= 0
    }

    //发送数据
    fun send(sendmsg:String):Int{
        return nnjni.send(pairsocket,sendmsg);
    }

    //接收数据
    fun recv():String{
        return nnjni.recv(pairsocket)
    }
}

几行简单的代码就已经实现了,接下来就是在Activity中调用实现了

MainActivity

代码语言:javascript
复制
package dem.vac.androidnanomsg

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Adapter
import android.widget.ArrayAdapter
import android.widget.SpinnerAdapter
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    private var nanotype = arrayOf("PAIR", "REQREP", "PUBSUB", "SURVEY")

    private var nnpair: NNPAIR? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        var adapter = ArrayAdapter(
            this,
            android.R.layout.simple_list_item_1, nanotype
        )
        spnnanotype.adapter = adapter

        btnConnent.setOnClickListener {
            if (nnpair == null) {
                nnpair = NNPAIR()
            }
            nnpair.let {
                if (it?.connect(edtipadr.text.toString())!!) {
                    tvmsg.text = "PAIR连接成功!\r\n"
                } else {
                    tvmsg.text = "PAIR连接失败!\r\n"
                }
            }
        }


        btnSend.setOnClickListener {

            nnpair.let {
                try {
                    //发送数据
                    it?.send(edtinput.text.toString())
                    //延时50毫秒
                    Thread.sleep(50)
                    //接收数据
                    val recvmsg = it?.recv()
                    tvmsg.append(recvmsg + "\r\n")
                } catch (e: IllegalArgumentException) {
                    tvmsg.append(e.message.toString() + "\r\n")
                }
            }
        }
    }


}

实现效果

Demo地址

https://github.com/Vaccae/NanoMsg4Android.git

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-02-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 微卡智享 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • NanoMsgJNI
  • native-lib.cpp
  • NNPAIR
  • MainActivity
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档