Server - JAVA
package com.jim.ndkdemo; import android.net.LocalServerSocket; import android.net.LocalSocket; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.widget.TextView; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; class ServerSocketThread extends Thread { public static String TAG = "zjm"; private boolean keepRunning = true; private LocalServerSocket serverSocket; private void readMsg(LocalSocket interactClientSocket) { StringBuilder recvStrBuilder = new StringBuilder(); InputStream inputStream = null; try { inputStream = interactClientSocket.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream); char[] buf = new char[4096]; int readBytes = -1; while ((readBytes = inputStreamReader.read(buf)) != -1) { String tempStr = new String(buf, 0, readBytes); recvStrBuilder.append(tempStr); } Log.d(TAG, "Receive MSG: " + recvStrBuilder.toString()); } catch (IOException e) { e.printStackTrace(); Log.d(TAG, "resolve data error !"); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Override public void run() { try { serverSocket = new LocalServerSocket("pym_local_socket"); } catch (IOException e) { e.printStackTrace(); keepRunning = false; } while(keepRunning) { Log.d(TAG, "wait for new client coming !"); try { LocalSocket interactClientSocket = serverSocket.accept(); //由于accept()在阻塞时,可能Activity已经finish掉了,所以再次检查keepRunning if (keepRunning) { Log.d(TAG, "new client coming !"); readMsg(interactClientSocket); } } catch (IOException e) { e.printStackTrace(); keepRunning = false; } } if (serverSocket != null) { try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } } public class MainActivity extends AppCompatActivity { public static String TAG = "zjm"; private ServerSocketThread socketThread; // Used to load the 'native-lib' library on application startup. static { System.loadLibrary("native-lib"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); socketThread = new ServerSocketThread(); socketThread.setName("zjmserver"); socketThread.start(); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } // Example of a call to a native method TextView tv = (TextView) findViewById(R.id.sample_text); tv.setText(stringFromJNI()); } /** * A native method that is implemented by the 'native-lib' native library, * which is packaged with this application. */ public native String stringFromJNI(); }
Client - C++
#include <jni.h> #include <string> #include <android/log.h> #include <sys/socket.h> #include <sys/un.h> #include <stddef.h> #include <stdio.h> #include <string.h> #include <unistd.h> #define ANDROID_SOCKET_NAMESPACE_ABSTRACT 0 #define NO_ERR 0 #define CREATE_ERR -1 #define CONNECT_ERR -2 #define LINUX_MAKE_ADDRUN_ERROR -3 #define CLOSE_ERR -5 #define LOG_TAG "zjm" #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) /* 构造sockaddr_un */ int socket_make_sockaddr_un(const char *name, int namespaceId, struct sockaddr_un *p_addr, socklen_t *socklen) { size_t namelen; memset(p_addr, 0x00, sizeof(*p_addr)); namelen = strlen(name); // Test with length +1 for the *initial* ' '. if ((namelen + 1) > sizeof(p_addr->sun_path)) { return LINUX_MAKE_ADDRUN_ERROR; } p_addr->sun_path[0] = 0; memcpy(p_addr->sun_path + 1, name, namelen); p_addr->sun_family = AF_LOCAL; *socklen = namelen + offsetof(struct sockaddr_un, sun_path) + 1; return NO_ERR; } /* 连接到相应的fileDescriptor上 */ int socket_local_client_connect(int fd, const char *name, int namespaceId, int type) { struct sockaddr_un addr; socklen_t socklen; //size_t namelen; int ret; ret = socket_make_sockaddr_un(name, namespaceId, &addr, &socklen); if (ret < 0) { return ret; } if(connect(fd, (struct sockaddr *) &addr, socklen) < 0) { return CONNECT_ERR; } return fd; } /* 创建本地socket客户端 */ int socket_local_client(const char *name, int namespaceId, int type) { int socketID; int ret; socketID = socket(AF_LOCAL, type, 0); if(socketID < 0) { return CREATE_ERR; } ret = socket_local_client_connect(socketID, name, namespaceId, type); if (ret < 0) { close(socketID); return ret; } return socketID; } int SendMsgBySocket() { int socketID; struct sockaddr_un serverAddr; char path[] = "pym_local_socket "; int ret; socketID = socket_local_client(path, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM); if (socketID < 0) { return socketID; } //Send Msg char buf[] = "hello"; ret = write(socketID, buf, strlen(buf)); ret = close(socketID); if (ret < 0) { return CLOSE_ERR; } return NO_ERR; } extern "C" JNIEXPORT jstring JNICALL Java_com_jim_ndkdemo_MainActivity_stringFromJNI( JNIEnv *env, jobject /* this */) { std::string hello = "Hello from C++"; int pid = fork(); if (pid == 0) { //sub process setpgid(0, 0); int ret = SendMsgBySocket(); LOGI("ret = %d", ret); } else if (pid > 0) { //int ret = SendMsgBySocket(); //LOGI("ret = %d", ret); } else { LOGI("pid < 0"); } sleep(1); return env->NewStringUTF(hello.c_str()); }