NanoMsg框架|C++的相关函数介绍及AndroidNDK的简单使用

学更好的别人,

做更好的自己。

——《微卡智享》

本文长度为6389,预计阅读11分钟

写在最前

前面的文章我们已经把C#通过NNanoMsg实现通讯的Demo说完了,本章开始介绍Android的通讯,通过NDK的方式主要是C++的调用,所以开始我们还是要先介绍一下怎么通过C或C++的调用NanoMsg。

NanoMsg相关函数

微卡智享

下面我们就列一下几个常用的函数,基本的通讯也就是用这几个函数进行处理的。

函数简单介绍
nn_socket
创建一个套接字
nn_setsockopt
设置套接字的选项
nn_bind
绑定地址
nn_connect
连接另一个套接字
nn_send
发送数据
nn_recv
接收数据

nn_socket

所在头文件:#include <nanomsg/nn.h>,作用为创建一个套接字。

int nn_socket (int domain, int protocol); 

参数:

domain:这个参数有两个格式,AF_SP和AF_SP_RAW,AF_SP表示标准的格式,AF_SP_RAW表示一种原始的格式,一般开发使用AF_SP即可。

protocol:设置通讯协议类型。如NN_PAIR等。

返回值:返回套接字。

nn_setsockopt

所在头文件:#include <nanomsg/nn.h>,作用和原始socket开发中的setsockopt类似,用来设置套接字的选项。

int nn_setsockopt (int s, int level, int option, const void *optval, size_t optvallen);

参数:

s:上面的函数nn_socket的返回值;

level:默认正常0即可(即NN_SOL_SOCKET);

option:需要改变的选项,一般我们来说主要就是设置超时这块的设置(即NN_SNDTIMEO和NN_RCVTIMEO);

*optval:上一个option参数对应的值;

optvallen:上一个*optval参数的长度;

返回值:返回不为零表示失败。

nn_bind

所在头文件:#include <nanomsg/nn.h>,作用绑定地址。

int nn_bind (int s, const char *addr);

参数:

s:上面的函数nn_socket的返回值;

*addr:地址;

返回值:返回小于零表示失败。

nn_connect

所在头文件:#include <nanomsg/nn.h>,作用连接另一个套接字。

int nn_connect(int s, const char *addr);

参数:

s:上面的函数nn_socket的返回值;

*addr:连接的地址;

返回值:返回小于零表示失败。

nn_send

所在头文件:#include <nanomsg/nn.h>,作用发送数据。

int nn_send (int s, const void *buf, size_t len, int flags);

参数:

s:上面的函数nn_socket的返回值;

*buf:发送的数据;

len:发送数据的长度;

flags:0表示在阻塞模式下执行,1(NN_DONTWAIT),表示在非阻塞模式下执行。

返回值:返回发送数据的长度,小于零表示错误。

nn_recv

所在头文件:#include <nanomsg/nn.h>,作用接收数据。

int nn_recv(int s,void * buf,size_t len,int flags);

参数:

s:上面的函数nn_socket的返回值;

*buf:接收的数据;

len:接收数据的最大长度;

flags:0表示在阻塞模式下执行,1(NN_DONTWAIT),表示在非阻塞模式下执行。

返回值:返回接收到的数据长度。

Android的NDK的简单调用

微卡智享

我们用Android Studio新建了一个C++的项目名称为AndroidNanoMsg

配置CMakeLists

配置CMakeList中我们要指定上一篇《NanoMsg框架|Android Studio编译NanoMsg源码》编译的动态库的路径,根据自己设置的路径自行修改,这里是我自己的路径D:\Business\DemoTEST\nanomsgtest\NanoMsg4Android\MakeNanomsgLib,所以我就要改为这个,如果你自己的不同这里也进行修改

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html


# Sets the minimum version of CMake required to build the native library.


cmake_minimum_required(VERSION 3.4.1)




#定义程序的目录,后面通过这个来关键编译好的动态库和头文件
#我们自己如果要修改目录只改这个地方就可以了
set(nanomsgpath "D:/Business/DemoTEST/nanomsgtest/NanoMsg4Android/MakeNanomsgLib/app")


#定义库文件的目录
set(nanomsglibpath ${nanomsgpath}/build/intermediates/cmake/debug/obj)




#调用头文件的具体路径
include_directories(${nanomsgpath}/src/main/cpp/src)
include_directories(${nanomsgpath}/src/main/cpp/src/utils)


#增加我们的动态库
add_library(libnanomsg SHARED IMPORTED)


#建立链接
set_target_properties(libnanomsg PROPERTIES IMPORTED_LOCATION
        "${nanomsglibpath}/${ANDROID_ABI}/libnanomsg.so")


# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.


add_library( # Sets the name of the library.
        native-lib


        # Sets the library as a shared library.
        SHARED


        # Provides a relative path to your source file(s).
        native-lib.cpp)


# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.


find_library( # Sets the name of the path variable.
        log-lib


        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log)


# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.


target_link_libraries( # Specifies the target library.
        native-lib
        libnanomsg


        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})

配置build.gradle

在build.gradle主要就是加上动态库的SourceSets,这样打包的时候会一起加入进去

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.2"
    defaultConfig {
        applicationId "dem.vac.androidnanomsg"
        minSdkVersion 14
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                cppFlags "-std=c++11"
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"


        }
    }


    //加上
    sourceSets{
        main{
            //当前这个目录下的库文件会被调用并且被打包进apk中
            jniLibs.srcDirs = ['D:/Business/DemoTEST/nanomsgtest/NanoMsg4Android/MakeNanomsgLib/app/build/intermediates/cmake/debug/obj']
        }
    }


}

通过上面两步,我们NDK的基本配置就完成了,接下来我们就开始做PAIR的测试。

C++中的调用方法

下面是一个简单的PAIR的调用方法,写在了一nanomsgtest方法中



extern "C" JNIEXPORT jstring JNICALL
Java_dem_vac_nanomsgdemo_MainActivity_nanomsgtest
        (JNIEnv *env, jobject, jstring ipadr_, jstring sendmsg_) {


    char *reschar;
    //设置超时地址
    int timeo = 5000;


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


    //拼接地址
    int len = strlen(ipadress) + strlen(ipadrpre);
    char str[len];
    strcpy(str, ipadrpre);
    strcat(str, ipadress);


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


    try {
        //创建PAIR的套接字
        int pair_socket = nn_socket(AF_SP, NN_PAIR);
        if (pair_socket == -1) {
            throw "nn_socket failed! error";
        }


        //设置超时
        int rc;
        rc = nn_setsockopt(pair_socket, 0, NN_SNDTIMEO, &timeo, sizeof(timeo));
        rc = nn_setsockopt(pair_socket, 0, NN_RCVTIMEO, &timeo, sizeof(timeo));


        //连接服务器
        rc = nn_connect(pair_socket, str);
        if (rc < 0) {
            throw "nn_connect failed! error";
        }


        char buf[256] = {0};
        //计算长度
        int str_len = strlen(sendmsg);
        //将sendmsg复制到buf中
        memcpy(buf, sendmsg, str_len);


        //发送数据
        rc = nn_send(pair_socket, buf, str_len, 0);
        if (rc < 0) {
            throw "nn_send failed! error";
        }


        //接收数据
        char buffer[256];
        rc = nn_recv(pair_socket, buffer, 256, 0);
        if (rc < 0) {
            throw "nn_recv failed! error";
        }


        char bufrecv[250] = {0};
        //将sendmsg复制到buf中
        memcpy(bufrecv, buffer, rc);


        reschar = bufrecv;
        LOGI("%s\n", reschar);


        memset(buffer, 0, 256);
        //关闭套接字
        nn_close(pair_socket);
    } catch (char *e) {
        reschar = e;
    }
    return env->NewStringUTF(reschar);
}


对应的MainActivity中

class MainActivity : AppCompatActivity() {


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


        // Example of a call to a native method
        sample_text.text = stringFromJNI()


        btnsend.setOnClickListener {
            var resstr = ""
            try {
                sample_text.text = "通讯中"
                var ipadr = edtipadr.text.toString()
                var sendmsg = "我发个试试";
                resstr = nanomsgtest(ipadr, sendmsg)
                sample_text.text = resstr
            } catch (e: Exception) {
                Log.i("ndk", e.message)
                sample_text.text = e.message
            }


        }
    }




    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */
    external fun stringFromJNI(): String


    external fun nanomsgtest(ipadr: String, sendmsg: String): String




    companion object {


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

按上面的写法,一个简单的NanoMsg的调用就已经实现了,下一篇我们来写一下关于NanoMsg在NDK中的简单的封装,方便不会NDK的同学直接调用。

扫描二维码

获取更多精彩

微卡智享

「 往期文章 」

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

NanoMsg框架|Android Studio编译NanoMsg源码

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Vaccae

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

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

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

打赏作者

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

抵扣说明:

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

余额充值