Подключение сокетов Android BSD

У меня возникли некоторые проблемы при попытке подключить клиентский сокет BSD к серверу. Создание и подключение сокетов реализовано с помощью JNI. Фактическое соединение устанавливается через код Java.

JNI часть:

#include <jni.h>

#include <unistd.h>
#include <string.h>

#include <sys/endian.h>
#include <sys/ioctl.h>

#include <sys/errno.h>
#include <sys/socket.h>
#include <sys/poll.h>
#include <netinet/in.h>

JNIEXPORT jint JNICALL Java_com_example_socketclinet_Native_socket
(JNIEnv *, jclass, jint, jint, jint);

JNIEXPORT jint JNICALL Java_com_example_socketclinet_Native_connect
(JNIEnv *, jclass, jint, jint, jint);

jint JNICALL Java_com_example_socketclinet_Native_socket
(JNIEnv *env, jclass cls, jint domain, jint type, jint protocol)
{
    return socket(domain, type, protocol);
}

jint JNICALL Java_com_example_socketclinet_Native_connect
(JNIEnv *env, jclass cls, jint socket, jint address, jint port)
{
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(struct sockaddr_in));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(address);
    addr.sin_port = htons(port);
    return connect(socket, (const struct sockaddr *)&addr, sizeof(struct sockaddr_in));
}

Класс собственного моста Java:

class Native
{
    static
    {
        System.loadLibrary("mylib");
    }

    public static final int SOCK_STREAM = 2;
    public static final int AF_INET = 2;

    public static native int socket(int domain, int type, int protocol);
    public static native int connect(int socket, int address, int port);
}

Использование собственного класса:

int socket = Native.socket(Native.AF_INET, Native.SOCK_STREAM, 0);
if (socket < 0)
{
    System.err.println("Socket error: " + socket);
    return;
}

byte[] address = { .... }; // 192.168.xxx.xxx
int addr = address[0] << 24 | address[1] << 16 | address[2] << 8 | address[3];
int port = ....;

int result = Native.connect(socket, addr, port);
if (result < 0)
{
    System.err.println("Connection failed: " + result);
}
else
{
    System.out.println("Connected");
}

Метод «connect» всегда возвращает «0», даже если сервер не работает (как на устройстве, так и на симуляторе).

• У меня есть разрешение "ИНТЕРНЕТ" с файлом манифеста (без него функция "сокет" возвращает -1)
• Тот же код отлично работает на iOS и Mac OS.
• Среда тестирования: Nexus 5 (4.4). .4), android-ndk-r10d

Любая помощь будет принята с благодарностью!


person Alex Lementuev    schedule 08.01.2015    source источник


Ответы (1)


byte[] подписан на Java, что означает, что ваш |addr| скорее всего расчет неверный. Я подозреваю, что вы подключаетесь к широковещательному адресу, который всегда будет успешным по определению.

Попробуйте распечатать адрес из собственного кода, чтобы убедиться, что в противном случае попробуйте заменить вычисление на:

int addr = (address[0] & 255) << 24 | 
           (address[1] & 255) << 16 |
           (address[2] & 255) <<  8 |
           (address[3] & 255);

Чтобы увидеть, решит ли это проблему.

person Digit    schedule 08.01.2015
comment
Вы не можете подключить сокет TCP к широковещательному адресу. - person user207421; 09.01.2015
comment
@Цифра, это не сработало. Кроме того, пытался жестко закодировать адрес в нативном коде - не повезло. В итоге я написал код связи сокета на java и добавил привязку JNI (сработало как шарм). - person Alex Lementuev; 09.01.2015