小编典典

使用JNI / C ++代码中的Java套接字

java

我有一个Java应用程序,它创建一个套接字来与服务器进程进行通信,例如,新的java.net.Socket(String host,int
port)。该应用程序包括一堆旧的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));

在具有多个NIC(例如,有线和wifi或vpn连接)的Windows vista /
7计算机上,这两个插槽可以以不同的本地地址结尾。Java代码似乎选择了“更好”的接口(有线Gb enet
=更高的MTU?),本机(天真?)代码获得了“默认”接口(粘贴在USB wifi设备中,它成为您的默认设置-讨厌) 。

这给我带来了一些问题,我认为细节不重要。两个问题:

  1. 对我来说,可以重用JNI代码中的java套接字(是否可以使用Sun JDK)。这样可以完全避免问题,但是到目前为止,我还没有看到任何与JNI /本地代码中的java.net.Socket交互的方法。

  2. 由于第一个问题的答案可能是“否”,因此java如何创建该套接字(选择接口)?欢迎使用代码段。我到处都是openjdk的东西,却没有找到我想要的东西。

谢谢克里斯


阅读 166

收藏
2020-11-16

共1个答案

小编典典

要回答您的第一个问题:如果可以在本机代码中重用Java的套接字,可以,但是我不建议这样做(您将自己绑定到特定实现/版本的内部);但是,如果您确实必须这样做:使用反射访问java.net.SocketImpl上的java.io.FileDescriptor,然后使用sun.misc。JavaIOFileDescriptorAccess的get方法获取本机套接字描述符。签出DualStackPlainSocketImpl.java

回答您的第二个问题:在Windows上查找默认接口的Java算法是什么?在net_util_md.c中检出getDefaultIPv6Interface方法(不要让v6欺骗您-
我相信它也用于v4)。

我建议您从C(JNI)代码或Java代码(最好是从Java代码)打开并使用套接字,因为您会发现最好在管理套接字的代码中处理清理和错误处理。在Java中打开套接字并从C(JNI)传递字节缓冲区的想法是完全明智的,并且在合理的缓冲区大小和JNI代码中的正确释放方面,您不会发现堆有任何问题。

想想Java应用程序服务器可以毫不费力地处理大量数据。

2020-11-16