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
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