Первым делом - нам нужно получить файловый дескриптор java.net.Socket
. Это можно сделать с помощью механизма отражения. Идея состоит в том, чтобы получить доступ к java.io.FileDescriptor
на java.net.SocketImpl
, а затем получить собственный дескриптор сокета. См. DualStackPlainSocketImpl.java
для фрагментов кода (этот метод также указан Зораном Регвартом здесь ).
Другой метод заключается в использовании JNI, как обсуждено здесь , вот пример:
static int getFd(JNIEnv *env, jobject sock)
{
JNIEnv e = *env;
jclass clazz;
jfieldID fid;
jobject impl;
jobject fdesc;
/* get the SocketImpl from the Socket */
if (!(clazz = e->GetObjectClass(env,sock)) ||
!(fid = e->GetFieldID(env,clazz,"impl","Ljava/net/SocketImpl;")) ||
!(impl = e->GetObjectField(env,sock,fid))) return -1;
/* get the FileDescriptor from the SocketImpl */
if (!(clazz = e->GetObjectClass(env,impl)) ||
!(fid = e->GetFieldID(env,clazz,"fd","Ljava/io/FileDescriptor;")) ||
!(fdesc = e->GetObjectField(env,impl,fid))) return -1;
/* get the fd from the FileDescriptor */
if (!(clazz = e->GetObjectClass(env,fdesc)) ||
!(fid = e->GetFieldID(env,clazz,"fd","I"))) return -1;
/* return the descriptor */
return e->GetIntField(env,fdesc,fid);
}
Полагаю, вы говорите о TCP-сокете Boost.Asio. Если это так, то вы должны связать собственный сокет с объектом сокета Asio, используя метод assign
.
Имейте в виду, что это решение может не работать для определенных реализаций Java, так как оно использует внутренние детали реализации, которые, как гарантируют, не останутся прежними. Кроме того, убедитесь, что нет параллелизма (т.е. Java не пытается читать из одного и того же дескриптора сокета параллельно) и т. Д. Другими словами - используйте на свой страх и риск.
Надеюсь, это поможет. Удачи!