Используя Java снабжают сокетом от JNI / код C++

У меня есть приложение Java, которое создает сокет, чтобы говорить с серверным процессом, например, новым java.net. Сокет (Строковый хост, международный порт). Это приложение включает набор кода C++ прежней версии, который должен высосать рты данных из того сервера и обработать его. Это в настоящее время реализуется при наличии собственного кода, создают его собственный сокет и подключение к серверу, например:

sock = socket(AF_INET, SOCK_STREAM, 0);
struct hostent* hp = gethostbyname(host);
if (!hp)
{
  unsigned long addr = inet_addr(host);
  hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET);
}

struct sockaddr_in name;
name.sin_family = AF_INET;
memcpy(&name.sin_addr, hp->h_addr, hp->h_length);
name.sin_port = htons(port);

connect(sock, (sockaddr*)&name, sizeof(name));

На машинах перспективы/7 Windows с несколькими NICs (например, соединенный проводом и Wi-Fi или соединения VPN), эти два сокета могут закончиться с различными локальными адресами. Код Java, кажется, выбирает "лучший" интерфейс (проводной Гбит enet = более высокий MTU?), собственный компонент (наивный?) код добирается, интерфейс "по умолчанию" (всуньте устройство Wi-Fi usb, и это становится Вашим значением по умолчанию - фу).

Это вызывает некоторые проблемы для меня, я не думаю, что детали релевантны. Два вопроса:

  1. Возможно для меня снова использовать сокет Java от кода JNI (портативно? примите Sun JDK). Это избежало бы проблемы полностью, но до сих пор я не вижу способа взаимодействовать с java.net. Материал сокета от JNI/собственного кода.

  2. Так как ответ на первый вопрос, вероятно, нет, как Java создает тот сокет (выбирающий интерфейс)? Фрагменты кода одобрены. Я осмотрел в материале openjdk и не нашел то, что я ищу.

Спасибо, Chris

10
задан Chris Morley 5 February 2010 в 14:36
поделиться

5 ответов

Чтобы ответить на ваш первый вопрос: возможно ли повторно использовать сокет Java из нативного кода - да, это возможно, но я бы не рекомендовал это (вы бы привязали себя к внутренней части конкретной реализации / версии); но если вам действительно необходимо: используйте отражение, чтобы получить доступ к java.io.FileDescriptor на java.net.SocketImpl, тогда используйте sun.misc. Метод get JavaIOFileDescriptorAccess для получения дескриптора собственного сокета. Оформить заказ DualStackPlainSocketImpl.java )

Чтобы ответить на ваш второй вопрос: каков алгоритм Java для поиска интерфейса по умолчанию в Windows - проверьте метод getDefaultIPv6Interface в net_util_md.c (не позволяйте v6 вводит вас в заблуждение - я считаю, что он используется и для v4).

Я бы посоветовал вам открыть и использовать сокет либо из кода C (JNI), либо из кода Java, желательно более позднего, поскольку вы обнаружите, что очистка и обработка ошибок лучше всего обрабатываются в коде, который управляет разъем. Идея открытия сокета в Java и передачи байтовых буферов из C (JNI) совершенно разумна, и вы не должны найти никаких проблем с кучей при разумных размерах буфера и правильном освобождении в коде JNI.

Подумайте о серверах приложений Java, которые без проблем обрабатывают огромные объемы данных.

10
ответ дан 4 December 2019 в 00:24
поделиться

Ваш второй вопрос-

Вы всегда можете «привязать» к нужному локальному интерфейсу (для этого нужен только IP-адрес)

public void bind (SocketAddress addr) выбрасывает SocketException Связывает этот DatagramSocket с определенным адресом и портом

0
ответ дан 4 December 2019 в 00:24
поделиться

Для вашего первого вопроса, если у вас есть Ссылка на объект java.net.Socket в вашем коде JNI, вы можете вызывать для него методы и, таким образом, вы можете читать и записывать данные через сокет.

1
ответ дан 4 December 2019 в 00:24
поделиться

Остерегайтесь решений, которые ковыряются в особенностях реализации JVM, они могут выйти из строя в будущем или с виртуальными машинами других поставщиков. Есть способ сделать это переносимо, используя API java.nio . Существуют методы для связи с каналами из машинного кода без копирования буферов в / из кучи java.

Основная идея состоит в том, чтобы создать java.nio.SocketChannel в вашем Java-коде, чтобы открыть соединение. Затем в C ++ используйте NewDirectByteBuffer , чтобы создать экземпляр java.nio.ByteBuffer , который можно передать методам read / write экземпляр канала.

См. Усовершенствования JNI, представленные в версии 1.4 Java 2 SDK и Новые API ввода-вывода , чтобы узнать подробности.

1
ответ дан 4 December 2019 в 00:24
поделиться

Я не могу придумать причину, по которой Java выбрала бы «лучший» локальный интерфейс, чем стандартный код. Все, что он делает, это вызывает собственный код, очень похожий на тот, который у вас есть. Возможно, вы видите что-то, что зависит от порядка, а не от Java.

0
ответ дан 4 December 2019 в 00:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: