Java 使用JNI/C++;代码
我有一个java应用程序,它创建了一个与服务器进程对话的套接字,例如新的java.net.socket(stringhost,int-port)。这个应用程序包括一组遗留的C++代码,需要从服务器中抽取大量数据并处理它。目前,这是通过让本机代码创建自己的套接字并连接到服务器来实现的,例如:Java 使用JNI/C++;代码,java,c++,sockets,java-native-interface,Java,C++,Sockets,Java Native Interface,我有一个java应用程序,它创建了一个与服务器进程对话的套接字,例如新的java.net.socket(stringhost,int-port)。这个应用程序包括一组遗留的C++代码,需要从服务器中抽取大量数据并处理它。目前,这是通过让本机代码创建自己的套接字并连接到服务器来实现的,例如: sock = socket(AF_INET, SOCK_STREAM, 0); struct hostent* hp = gethostbyname(host); if (!hp) { unsigned
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));
在具有多个NIC(如有线和wifi或vpn连接)的Windows vista/7计算机上,这两个套接字最终可能具有不同的本地地址。java代码似乎选择了一个“更好”的接口(有线Gb enet=更高的MTU?),而本地(naive?)代码则选择了“默认”接口(插入usb wifi设备,它会成为您的默认接口-真恶心)
这给我带来了一些问题,我不认为细节是相关的。两个问题:
Chris对于第一个问题,如果您的JNI代码中有一个
java.net.Socket
对象引用,您可以调用它上的方法,这样您就可以通过Socket读写数据了。您的第二个问题-
您可以始终“绑定”到所需的本地接口(只需要它的Ip地址)
公共无效绑定(SocketAddress addr)
抛出SocketException将此DatagramSocket绑定到特定的地址和端口以回答您的第一个问题:如果可以从本机代码中重用Java的socket——是的,这是可能的,但我不建议这样做(您将自己绑定到特定实现/版本的内部);但如果您确实必须:使用反射来访问java.net.SocketImpl上的java.io.FileDescriptor,然后使用sun.misc。JavaIOFileDescriptorAccess的get方法来获取本机套接字描述符。结帐) 回答您的第二个问题:在windows上查找默认接口的Java算法是什么——签出getDefaultIPv6Interface方法(不要让v6愚弄您——我相信它也用于v4) 我建议您从C(JNI)代码或Java代码(最好是后者)打开并使用套接字,因为您会发现清理和错误处理最好在管理套接字的代码中处理。在Java中打开套接字并从C(JNI)传递字节缓冲区的想法是完全正确的,并且在JNI代码中合理的缓冲区大小和适当的释放上,您不应该发现堆有任何问题
试想一下处理大量数据的Java应用程序服务器。小心那些涉及JVM实现细节的解决方案,它们很可能在将来或使用其他供应商的虚拟机时崩溃。有一种方法可以通过使用
java.nio
API进行移植。有一些方法可以从本机代码与通道通信,而无需将缓冲区复制到java堆或从java堆复制缓冲区
基本思想是在java代码中创建java.nio.SocketChannel
,以打开连接。然后在C++使用<代码> NewDirectByteBuffer < /C>中创建一个<代码> java .Nio。ByteBuffer < /C>实例,该实例可以传递到<实例> > <代码> > />代码>编写< /COD>通道实例的方法。
查看和了解详细信息。我想不出为什么Java会选择比启用代码“更好”的本地接口。它所做的只是调用本机代码,与您自己的代码非常相似。您可能会看到一些依赖顺序而不是依赖Java的内容。您可以提供一个SocketImpl子类,该子类具有自己的基于JNI函数的FileDescriptor,该函数公开了本机套接字。正如你在JNI中一样,你必须考虑平台(抽象),但是你独立于java实现,根据所接受的答案是主要风险。
SocketImpl类是由Socket.setSocketImplFactory()和合适的工厂部署的。在Java中调用bind听起来并没有什么帮助——它已经选择了最好的接口。但是获取Java套接字的本地地址,然后在本机端调用bind以使用相同的接口听起来是一种合理的方法。Ben,这实际上就是我所做的,但是我有一个报告说本机套接字无法连接到服务器(在将其绑定到与Java套接字相同的本地地址之后)。我还没有弄清楚它失败的原因,这就是我想看看java实现的原因。谢谢Zoran,我会看一看。-1建议在私有JVM实现细节中捣乱。你有没有读过这个问题,以及我对这个问题的回答?也许您希望提供一个不访问私有JVM实现细节的解决方案?不再提供“net_util_md.c”存储库。我可以想到几个原因,但我无法说出实际的原始原因。然而,正如佐兰所指出的,这种行为是不同的。java代码使用SIO_ROUTING_INTERFACE_查询调用WSAIoctl以获取接口。在这一点上,我倾向于完全摆脱本机套接字代码。