Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/198.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何通过重用会话连接到FTPS服务器?_Java_Android_Ftp_Ftps_Apache Commons Net - Fatal编程技术网

Java 如何通过重用会话连接到FTPS服务器?

Java 如何通过重用会话连接到FTPS服务器?,java,android,ftp,ftps,apache-commons-net,Java,Android,Ftp,Ftps,Apache Commons Net,我在android应用程序中使用Apache Commons FTP库 我正在尝试从我的应用程序(使用Android Studio)连接到我的FTPS服务器,然后上传一些文件 但是,当我想通过覆盖FTPSClient中的方法\u prepareDataSocket来重用会话时,我总是会遇到相同的错误:java.lang.NoSuchFieldException:sessionHostPortCache。 我尝试过其他帖子中的代码: 或 你知道我为什么会有这个错误吗 我正在使用Android st

我在android应用程序中使用Apache Commons FTP库

我正在尝试从我的应用程序(使用Android Studio)连接到我的FTPS服务器,然后上传一些文件

但是,当我想通过覆盖
FTPSClient
中的方法
\u prepareDataSocket
来重用会话时,我总是会遇到相同的错误:
java.lang.NoSuchFieldException:sessionHostPortCache
。 我尝试过其他帖子中的代码: 或 你知道我为什么会有这个错误吗

我正在使用Android studio和JDK1.8

谢谢你的帮助,谢谢

主要代码:
String server=“ftp.[HIDDEN]”;
int端口=21;
字符串user=“[HIDDEN]”;
字符串pass=“[HIDDEN]”;
System.setProperty(“jdk.tls.useExtendedMasterSecret”、“false”);
SSLSessionReuseFTPSClient ftpClient=新的SSLSessionReuseFTPSClient(“SSL”);
ftpClient.addProtocolCommandListener(新的PrintCommandListener(新的PrintWriter(System.out),true));
ftpClient.connect(服务器、端口);
System.out.println(“连接到“+端口上的“+服务器+”);
ftpClient.login(用户,通过);
ftpClient.execPBSZ(0);
FTP客户执行保护(“P”);
ftpClient.setFileType(FTP.BINARY文件类型);
ftpClient.enterLocalPassiveMode();
//传输文件
输入流输入;
输入=新文件输入流(本地);
ftpClient.storeFile(远程,输入);
input.close();
ftpClient.noop();//检查控制连接是否正常工作
ftpClient.logout();
SSLSessionReuseFTPSClient:
公共类SSLSessionReuseFTPSClient扩展了FTPSClient{
公共SSLSessionReuseFTPSClient(字符串协议){
超级(议定书);
}
//改编自:https://trac.cyberduck.io/changeset/10760
@凌驾
受保护的void\u prepareDataSocket\u(最终套接字)引发IOException{
if(SSLSocket的套接字实例){
//控制套接字是SSL
最终SSLSession会话=((SSLSocket)socket)。getSession();
if(session.isValid()){
最终SSLSessionContext=session.getSessionContext();
试一试{
最终字段sessionHostPortCache=context.getClass().getDeclaredField(“sessionHostPortCache”);
sessionHostPortCache.setAccessible(true);
最终对象缓存=sessionHostPortCache.get(上下文);
最终方法Method=cache.getClass().getDeclaredMethod(“put”,Object.class,Object.class);
方法setAccessible(true);
调用(缓存,字符串
.format(“%s:%s”、socket.getInetAddress().getHostName()、String.valueOf(socket.getPort())
.toLowerCase(Locale.ROOT),会话);
调用(缓存,字符串
.format(“%s:%s”、socket.getInetAddress().getHostAddress()、String.valueOf(socket.getPort()))
.toLowerCase(Locale.ROOT),会话);
}捕获(无此字段例外){
抛出新的IOException(e);
}捕获(例外e){
抛出新的IOException(e);
}
}否则{
抛出新IOException(“无效SSL会话”);
}
}
}
}
日志:
当我将java.security更改为使用ssl安全提供程序而不是SunJSSE时,我遇到了相同的错误。特别是在我的情况下,我将其更改为: security.provider.4=org.bouncycastle.jsse.provider.BouncyCastleJsseProvider 相反 security.provider.4=com.sun.net.ssl.internal.ssl.provider

1) 检查java.security文件

2) 我在类中添加了一条日志消息,它显示了实际使用的SSLSessionContext实现

logger.debug("sessionContext calss = " + sessionContext.getClass().getCanonicalName());
final Field sessionHostPortCache = sessionContext.getClass().getDeclaredField("sessionHostPortCache");
我确实找到了那个弹跳舱 org.bouncycastle.jsse.provider.ProvSSLSessionContext类没有sessionHostPortCache成员。 您可以尝试此方法来发现问题

获取java.lang.NoSuchFieldException的另一个原因是JRE字节码经历了混淆。因此,sessionHostPortCache字段可以命名为“b”


您可以通过在IDE中打开SSLSessionContext.class来检查这一点,如果您安装了反编译器插件,它将显示源代码。

这很可能是您正在使用的JDK/JRE的一些特殊之处(不同的
SSLSocket
)。您是否在桌面Java上测试了相同的代码?你应该缩小这个问题的范围以得到合适的答案。我重新下载了JDK1.8,但它仍然不起作用。对不起,我不明白你说的桌面java是什么意思。
logger.debug("sessionContext calss = " + sessionContext.getClass().getCanonicalName());
final Field sessionHostPortCache = sessionContext.getClass().getDeclaredField("sessionHostPortCache");