前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >NanoMsg框架|C++的相关函数介绍及AndroidNDK的简单使用

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

作者头像
Vaccae
发布2020-03-11 15:15:32
2.3K0
发布2020-03-11 15:15:32
举报
文章被收录于专栏:微卡智享微卡智享

学更好的别人,

做更好的自己。

——《微卡智享》

本文长度为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,所以我就要改为这个,如果你自己的不同这里也进行修改

代码语言:javascript
复制
# 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,这样打包的时候会一起加入进去

代码语言:javascript
复制
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方法中

代码语言:javascript
复制
extern "C" JNIEXPORT jstring JNICALLJava_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中

代码语言:javascript
复制
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的同学直接调用。

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 配置CMakeLists
  • 配置build.gradle
  • C++中的调用方法
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档