Mam program Linux podzielony na dwie części.W Javie, w jaki sposób uzyskać Socket lub DatagramSocket z deskryptora pliku już otwartego gniazda C?
Jedna część wykonuje translację NAT w celu uzyskania gniazda UDP (wykrywanie otworów UDP) lub gniazda TCP (dziurkowanie TCP). Część pierwsza została napisana w języku C, aby umożliwić natywne funkcje, które ułatwiają lub usprawniają proces translacji NAT. Część druga w rzeczywistości korzysta z podłączonego gniazda uzyskanego przez translację NAT wykonaną w części pierwszej.
Tutaj jest problem. Chcę, aby pierwsza część, część, która uzyskuje gniazdo, była niezależna od drugiej części, części, która używa gniazda do konkretnego zastosowania aplikacji. Na przykład chcę, aby pierwsza część była wielokrotnego użytku dla wielu różnych aplikacji, które wszystkie wymagają połączeń UDP i TCP, które zostały ustanowione między równorzędnymi.
W tej chwili chciałbym, aby druga część (część aplikacji) została napisana w Javie zamiast w C lub C++. Chcę, aby druga część używała połączenia z gniazdem, które zostało uzyskane przez kod C odpowiedzialny za przechodzenie NAT. Powiedzmy, że pierwsza część powstała z połączenia, a następnie zwraca struct:
// Represents a TCP or UDP connection that was obtained in part one.
struct ConnectionObtained {
int socket_file_descriptor;
int source_port;
int destination_port;
int source_address; // 4 byte ipv4 address
int destination_address;
int is_UDP; // 1 for UDP client socket, 0 for TCP client socket
};
Kod C w jednej części może zapewnić tę POD/struct do kodu Java w drugiej części za pośrednictwem JNI (Java Native Interface) lub poprzez komunikacja międzyprocesowa.
Chcę, aby kod Java użył tych informacji do skonstruowania obiektu, którego zadeklarowanym typem jest albo java.net.DatagramSocket lub java.net.Socket, a następnie użyj tego obiektu wszędzie tam, gdzie oczekiwano DatagramSocket lub Socket.
Jako punkt wyjścia, należy rozważyć następujący przykładowy kod ...
/**
* Determines the Unix file descriptor number of the given {@link ServerSocket}.
*/
private int getUnixFileDescriptor(ServerSocket ss) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
Field $impl=ss.getClass().getDeclaredField("impl");
$impl.setAccessible(true);
SocketImpl socketImpl=(SocketImpl)$impl.get(ss);
Method $getFileDescriptor=SocketImpl.class.getDeclaredMethod("getFileDescriptor");
$getFileDescriptor.setAccessible(true);
FileDescriptor fd=(FileDescriptor)$getFileDescriptor.invoke(socketImpl);
Field $fd=fd.getClass().getDeclaredField("fd");
$fd.setAccessible(true);
return (Integer)$fd.get(fd);
}
Kod sprawia, że wydaje się, że może to być możliwe, aby „odtwarza związanego {@link ServerSocket} na podanym deskryptorze pliku. " Czy to oznacza, że możliwe jest "odtworzenie powiązanego {@link java.net.Socket} na podanym deskryptorze pliku"? A co ze związanym {@link java.net.DatagramSocket}?
/**
* Recreates a bound {@link ServerSocket} on the given file descriptor.
*/
private ServerSocket recreateServerSocket(int fdn) throws Exception {
FileDescriptor fd=new FileDescriptor();
Field $fd=FileDescriptor.class.getDeclaredField("fd");
$fd.setAccessible(true);
$fd.set(fd,fdn);
Class $PlainSocketImpl=Class.forName("java.net.PlainSocketImpl");
Constructor $init=$PlainSocketImpl.getDeclaredConstructor(FileDescriptor.class);
$init.setAccessible(true);
SocketImpl socketImpl=(SocketImpl)$init.newInstance(fd);
ServerSocket ss=new ServerSocket();
ss.bind(new InetSocketAddress(0));
Field $impl=ServerSocket.class.getDeclaredField("impl");
$impl.setAccessible(true);
$impl.set(ss,socketImpl);
return ss;
}
Jeśli kod Java musi dotyczyć jedynie podłączonych gniazd, dlaczego Twój kod Java jest pełen trików na 'ServerSocket?' – EJP
Jeśli dobrze zrozumiałem, czy chcesz użyć istniejącego otwartego gniazda jako podstawowego gniazda nowe gniazdo klienta Java? – perencia
Możliwe dupe: http://stackoverflow.com/questions/1243546/can-i-get-a-java-socket-from-a-file-descriptor-number –