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

学更好的别人,

做更好的自己。

——《微卡智享》

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

前言

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

实现效果

封装思路

微卡智享

#说明
1通过JNI把几个核心函数进行处理
2把每种模式新建一个类用于单独处理相关的通讯

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

NanoMsgJNI

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

#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

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

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

扫描二维码

获取更多精彩

微卡智享

「 往期文章 」

NanoMsg框架|Android Studio编译NanoMsg源码

NanoMsg框架|C#中REQREP、PUBSUB和SURVEY使用(附Demo))

NanoMsg框架|C#中Nanomsg的PAIR和BUS使用

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Vaccae

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值