当前位置:网站首页>NDK learning notes (XI) POSIX sockect local communication

NDK learning notes (XI) POSIX sockect local communication

2022-06-11 05:34:00 Come and go

1. Local communication , Native server 、java client

In this case , The native code implements the local server ,java The code implements the local client . The local server uses the previous tcp Some methods of communication .

(1) Function introduction (C/C++)

Create native local socket

/** *  Create native local socket * @param env * @param obj * @return */
static int NewLocalSocket(JNIEnv *env, jobject obj) {
    

    LogMessage(env, obj, " To create local socket");
    int localSocket = socket(PF_LOCAL, SOCK_STREAM, 0);
    if (-1 == localSocket) {
    

        ThrowErrnoException(env, "java/io/IOException", errno);
    }
    return localSocket;
}

Will local socket And Name binding

Local socket Namespace :
Abstract namespace: In the local socket Maintenance in the communication protocol module ,socket Named after NULL Characters are bound to prefixes socket name .
Filesystem namespace: Through the file system with a special socket Form maintenance of documents ,socket Name is passed directly to sockaddr_un structure , take socket Name and socket binding .

/** *  Will local socket Bound to a name  * */
static void BindLocalSocketToName(JNIEnv *env, jobject obj, int sd, const char *name) {
    

    struct sockaddr_un address;
    // length 
    const size_t nameLength = strlen(name);
    size_t pathLength = nameLength;

    // If the name doesn't start with “/” start , It's in Abstract namespace
    bool abstractNamespace = ('/' != name[0]);

    // The abstract namespace requires that the first byte of the directory be 0 byte , The update path length includes 0 byte 
    if (abstractNamespace) {
    

        pathLength++;
    }

    if (pathLength > sizeof(address.sun_path)) {
    

        ThrowException(env, "java/io/IOException", " The name is too long ");
    } else {
    

        memset(&address, 0, sizeof(address));
        address.sun_family = PF_LOCAL;

        char *sunPath = address.sun_path;

        // The first byte must be 0 To use abstract namespaces 
        if (abstractNamespace) {
    

            *sunPath++ = NULL;
        }

        strcpy(sunPath, name);
        // Address length ,offsetof Will generate a file of type  size_t  Integer constant for , It is the byte offset of a structure member relative to the beginning of the structure .
        socklen_t addressLength = (offsetof(struct sockaddr_un, sun_path)) + pathLength;

        // If socket Name already bound , Cancel connection 
        unlink(address.sun_path);

        LogMessage(env, obj, " Bind to local name %s%s", (abstractNamespace) ? "(null)" : "", name);
        if (-1 == bind(sd, (struct sockaddr *) &address, addressLength)) {
    

            ThrowErrnoException(env, "java/io/IOException", errno);
        }
    }
}

Receive local socket

/** *  Block and wait socket Client connection on  * @param env * @param obj * @param sd * @return */
static int AcceptOnLocalSocket(JNIEnv *env, jobject obj, int sd) {
    

    LogMessage(env, obj, " Wait for the client to connect ");
    int clientSocket = accept(sd, NULL, NULL);
    if (-1 == clientSocket) {
    

        ThrowErrnoException(env, "java/io/IOException", errno);
    }
    return clientSocket;
}

start-up Socket Server

/** *  Start a local unix socket  The server  */
extern "C"
JNIEXPORT void JNICALL
Java_com_example_testnt_LocalEchoActivity_nativeStartLocalServer(JNIEnv *env, jobject thiz,
                                                                 jstring name) {
    

    int serverSocket = NewLocalSocket(env, thiz);
    if (NULL == env->ExceptionOccurred()) {
    

        const char *nameText = env->GetStringUTFChars(name, NULL);
        if (NULL == nameText) {
    

            goto exit;
        }
        // binding 
        BindLocalSocketToName(env, thiz, serverSocket, nameText);
        env->ReleaseStringUTFChars(name, nameText);

        if (NULL != env->ExceptionOccurred()) {
    
            goto exit;
        }

        ListenOnSocket(env, thiz, serverSocket, 4);

        if (NULL != env->ExceptionOccurred()) {
    

            goto exit;
        }

        int clientSocket = AcceptOnLocalSocket(env, thiz, serverSocket);
        if (NULL != env->ExceptionOccurred()) {
    
            goto exit;
        }
        char buffer[MAX_BUFFER_SZIE];
        ssize_t recvSize;
        ssize_t sentSize;
        while (1) {
    

            recvSize = ReceiveFromSocket(env, thiz, clientSocket, buffer, MAX_BUFFER_SZIE);
            if ((0 == recvSize) || (NULL != env->ExceptionOccurred())) {
    
                break;
            }
            sentSize = SendToSocker(env, thiz, clientSocket, buffer, (size_t) recvSize);
            if ((0 == sentSize) || (NULL != env->ExceptionOccurred())) {
    
                break;
            }
        }
        close(clientSocket);
    }
    exit:
    if (serverSocket > 0) {
    

        close(serverSocket);
    }
}

Running effect
 Insert picture description here
See the following link for detailed code , Start at runtime LocalEchoActivity Interface .

https://gitee.com/xd_box/NDK_Socket
原网站

版权声明
本文为[Come and go]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/03/202203020538239446.html