Android LocalServerSocket

后端 未结 4 1569
长发绾君心
长发绾君心 2021-02-02 02:02

In android, there are two classes LocalServerSocket and LocalSocket. I think they are something like AF_LOCAL in unix socket (I am not sure it is correct or not).

My que

4条回答
  •  萌比男神i
    2021-02-02 02:28

    Confirmed that the above works properly. The following examples will not only work together, but will work with the corresponding Android LocalSocket and LocalServerSocket classes:

    Client side (Android is server using LocalServerSocket):

    #include       /* for printf() and fprintf() */
    #include  /* for socket(), connect(), send(), and recv() */
    #include      /* struct sockaddr_un */
    #include      /* for atoi() and exit() */
    #include      /* for memset() */
    #include      /* for close() */
    #include 
    #include 
    
    #define RCVBUFSIZE 2048   /* Size of receive buffer */
    
    void DieWithError(char *errorMessage)  /* Error handling function */
    {
        fprintf(stderr, "Error: %s - %s\n", errorMessage, strerror(errno));
        exit(errno);
    }
    
    int main(int argc, char *argv[])
    {
        int sock;                        /* Socket descriptor */
        struct sockaddr_un echoServAddr; /* Echo server address */
        unsigned char *localSocketName = "MyTestSocket";
        static unsigned char echoString[] = {0x80, 0x00, 0x0e, 0x10, 0x00, 0x9c, 0x40, 0xc9, 0x20, 0x20, 0x20, 0x32, 0x00, 0x00};
        static unsigned int echoStringLen = sizeof(echoString); /* Length of string to echo */
        unsigned char echoBuffer[RCVBUFSIZE]; /* Buffer for echo string */
        int bytesRcvd, totalBytesRcvd;   /* Bytes read in single recv() 
                                        and total bytes read */
        int size;
        int i;
    
        /* Create a reliable, stream socket using Local Sockets */
        if ((sock = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0)
            DieWithError("socket() failed");
    
        /* Construct the server address structure */
        memset(&echoServAddr, 0, sizeof(echoServAddr));     /* Zero out structure */
        echoServAddr.sun_family      = AF_LOCAL;            /* Local socket address family */
        /**
         * Tricky and obscure! For a local socket to be in the "Android name space":
         * - The name of the socket must have a 0-byte value as the first character
         * - The linux man page is right in that 0 bytes are NOT treated as a null terminator.
         * - The man page is not clear in its meaning when it states that "the rest of the bytes in
         *        sunpath" are used. "Rest of bytes" is determined by the length passed in for
         *        sockaddr_len and Android sets this per the recommended file-system sockets of
         *        sizeof(sa_family_t) + strlen(sun_path) + 1. This is important when making calls
         *        to bind, connect, etc!
         * We have initialized the struct sockaddr_un to zero already, so all that is needed is to
         * begin the name copy at sun_path[1] and restrict its length to sizeof(echoServAddr.sun_path)-2
         **/
        strncpy(echoServAddr.sun_path + 1, localSocketName, sizeof(echoServAddr.sun_path) - 2); 
        size = sizeof(echoServAddr) - sizeof(echoServAddr.sun_path) + strlen(echoServAddr.sun_path+1) + 1;
    
        /* Establish the connection to the echo server */
        if (connect(sock, (struct sockaddr *) &echoServAddr, size) < 0)
            DieWithError("connect() failed");
    
        /* Send the string to the server */
        if (send(sock, echoString, echoStringLen, 0) != echoStringLen)
            DieWithError("send() sent a different number of bytes than expected");
    
        /* Receive the same string back from the server */
        totalBytesRcvd = 0;
        printf("Sent:     ");
        for (i = 0; i < echoStringLen; i++)
            printf("%02X ", echoString[i]);
        printf("\n");    /* Print a final linefeed */
    
        printf("Received: ");                /* Setup to print the echoed string */
        if ((bytesRcvd = recv(sock, echoBuffer, RCVBUFSIZE - 1, 0)) <= 0)
            DieWithError("recv() failed or connection closed prematurely");
        for (i = 0; i < bytesRcvd; i++)
            printf("%02X ", echoBuffer[i]);
        printf("\n");    /* Print a final linefeed */
    
        close(sock);
        exit(0);
    }
    

    Server side (Android is client using LocalSocket):

    #include       /* for printf() and fprintf() */
    #include  /* for socket(), connect(), send(), and recv() */
    #include      /* struct sockaddr_un */
    #include      /* for atoi() and exit() */
    #include      /* for memset() */
    #include      /* for close() */
    #include 
    #include 
    
    #define RCVBUFSIZE 2048   /* Size of receive buffer */
    
    void DieWithError(char *errorMessage)  /* Error handling function */
    {
        fprintf(stderr, "Error: %s - %s\n", errorMessage, strerror(errno));
        exit(errno);
    }
    
    void HandleLocalClient(int clntSocket)
    {
        char echoBuffer[RCVBUFSIZE];        /* Buffer for echo string */
        int recvMsgSize;                    /* Size of received message */
    
        /* Receive message from client */
        if ((recvMsgSize = recv(clntSocket, echoBuffer, RCVBUFSIZE, 0)) < 0)
            DieWithError("recv() failed");
    
        /* Send received string and receive again until end of transmission */
        while (recvMsgSize > 0)      /* zero indicates end of transmission */
        {
            /* Echo message back to client */
            if (send(clntSocket, echoBuffer, recvMsgSize, 0) != recvMsgSize)
                DieWithError("send() failed");
    
            /* See if there is more data to receive */
            if ((recvMsgSize = recv(clntSocket, echoBuffer, RCVBUFSIZE, 0)) < 0)
                DieWithError("recv() failed");
        }
    
        close(clntSocket);    /* Close client socket */
    }
    
    #define MAXPENDING 5    /* Maximum outstanding connection requests */
    
    void DieWithError(char *errorMessage);  /* Error handling function */
    void HandleLocalClient(int clntSocket);   /* TCP client handling function */
    
    int main(int argc, char *argv[])
    {
        int servSock;                    /* Socket descriptor for server */
        int clntSock;                    /* Socket descriptor for client */
        struct sockaddr_un echoClntAddr; /* Client address */
        unsigned int clntLen;            /* Length of client address data structure */
        struct sockaddr_un echoServAddr; /* Echo server address */
        unsigned char *localSocketName = "MyTestSocket";
        static unsigned int echoStringLen = 14;      /* Length of string to echo */
        unsigned char echoBuffer[RCVBUFSIZE];     /* Buffer for echo string */
        int bytesRcvd, totalBytesRcvd;   /* Bytes read in single recv() 
                                        and total bytes read */
        int size;
        int i;
    
        /* Create a reliable, stream socket using Local Sockets */
        if ((servSock = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0)
            DieWithError("socket() failed");
    
        /* Construct the server address structure */
        memset(&echoServAddr, 0, sizeof(echoServAddr));     /* Zero out structure */
        echoServAddr.sun_family      = AF_LOCAL;            /* Local socket address family */
        /**
         * Tricky and obscure! For a local socket to be in the "Android name space":
         * - The name of the socket must have a 0-byte value as the first character
         * - The linux man page is right in that 0 bytes are NOT treated as a null terminator.
         * - The man page is not clear in its meaning when it states that "the rest of the bytes in
         *        sunpath" are used. "Rest of bytes" is determined by the length passed in for
         *        sockaddr_len and Android sets this per the recommended file-system sockets of
         *        sizeof(sa_family_t) + strlen(sun_path) + 1. This is important when making calls
         *        to bind, connect, etc!
         * We have initialized the struct sockaddr_un to zero already, so all that is needed is to
         * begin the name copy at sun_path[1] and restrict its length to sizeof(echoServAddr.sun_path)-2
         **/
        strncpy(echoServAddr.sun_path + 1, localSocketName, sizeof(echoServAddr.sun_path) - 2); 
        size = sizeof(echoServAddr) - sizeof(echoServAddr.sun_path) + strlen(echoServAddr.sun_path+1) + 1;
    
        /* Bind to the local address */
        if (bind(servSock, (struct sockaddr *) &echoServAddr, size) < 0)
            DieWithError("bind() failed");
    
        /* Mark the socket so it will listen for incoming connections */
        if (listen(servSock, MAXPENDING) < 0)
            DieWithError("listen() failed");
    
        for (;;) /* Run forever */
        {
            /* Set the size of the in-out parameter */
            clntLen = sizeof(echoClntAddr);
    
            /* Wait for a client to connect */
            if ((clntSock = accept(servSock, (struct sockaddr *) &echoClntAddr, &clntLen)) < 0)
                DieWithError("accept() failed");
    
            /* clntSock is connected to a client! */
    
            printf("Handling client\n");
    
            HandleLocalClient(clntSock);
        }
        /* NOT REACHED */
        return 0;
    }
    

    Tested with Android 4.0.3 ICS 03/15

提交回复
热议问题