Ho un programma Linux diviso in due parti.In Java, come si ottiene un socket o DatagramSocket dal descrittore di file di un socket C già aperto?
Una parte attraversa NAT per ottenere un socket UDP (punzonatura UDP) o un socket TCP (punzonatura TCP). La prima parte è scritta in C per consentire funzionalità native che facilitano o migliorano il processo di attraversamento NAT. La seconda parte utilizza effettivamente la presa connessa ottenuta tramite l'attraversamento NAT eseguita nella prima parte.
Ora ecco il problema. Voglio che la prima parte, la parte che ottiene il socket, sia indipendente dalla seconda parte, la parte che utilizza il socket per uno scopo specifico dell'applicazione. Ad esempio, desidero che la prima parte sia riutilizzabile per una varietà di applicazioni diverse che hanno tutte bisogno di connessioni UDP e TCP stabilite tra pari.
In questo momento, vorrei che la seconda parte (la parte dell'applicazione) fosse scritta in Java anziché in C o C++. Voglio che la seconda parte utilizzi una connessione socket che è stata ottenuta dal codice C responsabile per NAT traversal. Diciamo che la prima parte stabilita una connessione e quindi restituisce una 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
};
Il codice C nella prima parte in grado di fornire questo POD/struct per il codice Java in parte due o tramite JNI (Java Native Interface) o tramite comunicazione inter-processista.
Desidero che il codice Java utilizzi tali informazioni per costruire un oggetto il cui tipo dichiarato è java.net.DatagramSocket o java.net.Socket e quindi utilizzare tale oggetto ovunque sia previsto un DatagramSocket o un socket.
Come punto di partenza, si consideri il seguente codice di esempio ...
/**
* 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);
}
Il codice fa sembrare che può essere possibile a "ricrea un balzo {@link ServerSocket} sul dato descrittore di file. " Questo significa che è possibile "ricreare un limite {@link java.net.Socket} sul descrittore di file specificato"? Che dire di un limite {@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;
}
Se il codice Java deve essere interessato solo ai socket connessi, perché il codice Java è pieno di trucchi sul 'ServerSocket?' – EJP
Se ho capito correttamente, si desidera utilizzare un socket aperto esistente come socket sottostante di un nuovo socket client Java? – perencia
Possibile dupe: http://stackoverflow.com/questions/1243546/can-i-get-a-java-socket-from-a-file-descriptor-number –