Существует Java-сервер LocalServerSocket, прослушивающий абстрактный сокет домена unix с именем myaudsocket, например:
public void listen() {
String name = "myaudsocket";
mSocket = new LocalServerSocket(name);
LocalSocket client = mSocket.accept();
...
}
Я могу подключить сервер с помощью кода Java ниже:
public void connect() {
String name = "myaudsocket";
LocalSocket client = new LocalSocket();
client.connect(new LocalSocketAddress(name));
Log.d("client", "connected to " + name);
}
Но если я не могу подключиться к серверу по нативному коду:
#define SOKET_NAME "@myaudsocket"
void connect() {
char* name = SOKET_NAME;
struct sockaddr_un addr;
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
perror("failed to create socket");
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, SOKET_NAME, sizeof(addr.sun_path)-1);
if (name[0] == '@')
addr.sun_path[0] = '\0';
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("failed to connect");
close(sock);
return -1;
}
...
}
Консоль всегда говорила: «не удалось подключиться: в соединении отказано». Но приведенный выше собственный код может работать в общей ОС Linux (например, Ubuntu).
Как я могу решить эту проблему?
@user207421 обратитесь к man7.org/linux/man-pages/man7/unix.7.html, сказано, что «абстрактный: абстрактный адрес сокета отличается (от пути сокета) тем, что sun_path[ 0] является нулевым байтом ('\0')."
Проблема в длине адреса. Из официального справочного примера https://man7.org/linux/man-pages/man7/unix.7.html параметр длины адреса для connect() равен sizeof(struct sockaddr_un).
Он может работать в обычной системе Linux (например, Ubuntu). Но он не может работать в андроиде. Из источника libcutils:
Мы видим, что длина адреса установлена в конце нулевого символа, не включая нули заполнения.
*alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
После изменения кода как:
#define SOKET_NAME "@myaudsocket"
void connect() {
char* name = SOKET_NAME;
struct sockaddr_un addr;
// add this variant
int alen;
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
perror("failed to create socket");
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, SOKET_NAME, sizeof(addr.sun_path)-1);
if (name[0] == '@')
addr.sun_path[0] = '\0';
// Added this line
alen = offsetof(struct sockaddr_un, sun_path) + strlen(name);
// change sizeof(addr) to alen
if (connect(sock, (struct sockaddr *)&addr, alen) < 0) {
perror("failed to connect");
close(sock);
return -1;
}
}
Оно работает.
Почему вы устанавливаете первый байт в NUL? Это последний байт, который должен быть NUL.