今天在windows上调试FTP下载文件时,出险线程假死,代码如下:

if (inputStream != null) {
byte[] data = null;
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
data = new byte[inputStream.available()];
int len = 0;
while ((len = inputStream.read(data)) != -1) {
outStream.write(data, 0, len);
}
data = outStream.toByteArray();
Base64.Encoder encoder = Base64.getEncoder();
re = encoder.encodeToString(data);
}  

通过打印日志排查到while死循环,查看read方法源码注释:

/* <p> If the length of <code>b</code> is zero, then no bytes are read and
* <code>0</code> is returned; otherwise, there is an attempt to read at
* least one byte. If no byte is available because the stream is at the
* end of the file, the value <code>-1</code> is returned; otherwise, at
* least one byte is read and stored into <code>b</code>.
*/
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}

在date字节数组长度为1时,read方法返回0,while出现死循环,原因是因为网络传输数据不及时,导致inputStream.available()方法未取到本地内存的字节数据返回0。

由于下载的文件大小不是很大,默认给了一个2048大小的字节数组,于是做了以下优化:

if (inputStream != null) {
byte[] data = null;
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
if (inputStream.available() == 0) {
data = new byte[2048];
} else {
data = new byte[inputStream.available()];
} int len = 0;
while ((len = inputStream.read(data)) != -1) {
outStream.write(data, 0, len);
}
data = outStream.toByteArray();
Base64.Encoder encoder = Base64.getEncoder();
re = encoder.encodeToString(data);
} 

  再次调试,问题解决。

但是,在将程序部署到Linux服务器上依然假死,

问题分析:

FTPClient调用retrieveFileStream线程假死

FTPClient.listFiles()或者FTPClient.retrieveFile()方法时,就停止在那里,什么反应都没有,出现假死状 态。于是各种网上资料查找

FTP的两种传输模式:主动模式被动模式

在调用这两个方法之前,调用 FTPClient.enterLocalPassiveMode();这个方法的意思就是每次数据连接之前,ftp client告诉ftp server开通一个端口来传输数据。因为ftp server可能每次开启不同的端口来传输数据,但是在linux上,由于防火墙安全限制,可能某些端口没有开启,所以就出现阻塞。

解决方法:ftpClient.enterLocalPassiveMode(); //开启本地被动模式,此代码设置在登陆之后或者之前都可以。

同样,如果上传的话需要enterRemotePassiveMode()//开启远程被动传输模式

感谢网络上的大神们的分享,不然又得钻牛角了。

解决FTPClient下载网络文件线程挂起问题的更多相关文章

  1. 解决FTPClient linux环境下FTPClient调用retrieveFileStream导致线程挂起(防火墙问题);下载文件小于实际文件问题

    FTPClient调用retrieveFileStream导致线程挂起(防火墙问题):下载文件小于实际文件问题解决 实际是因为FTP的两种传输模式:主动模式和被动模式的不同而导致的 FTPClient ...

  2. JAVA多线程下载网络文件

    JAVA多线程下载网络文件,开启多个线程,同时下载网络文件.   源码如下:(点击下载 MultiThreadDownload.java) import java.io.InputStream; im ...

  3. Java读取并下载网络文件

      CreateTime--2017年8月21日10:11:07 Author:Marydon import java.io.ByteArrayOutputStream; import java.io ...

  4. python下载网络文件

    python下载网络文件 制作人:全心全意 下载图片 #!/usr/bin/python #-*- coding: utf-8 -*- import requests url = "http ...

  5. C#限速下载网络文件

    代码: using System; using System.Collections.Concurrent; using System.Collections.Generic; using Syste ...

  6. DELPHI TDownLoadURL下载网络文件

      DELPHI XE6 FMX 附件:http://files.cnblogs.com/xe2011/IDHttp_fmx.7z unit Unit1; interface uses //引用 Vc ...

  7. 解决FTPClient上传文件为空,显示0字节

    JAVA使用FTPClient上传文件时总是为空,而使用FileZilla客户端时却不会. 后来查了下资料,FTP服务器有被动模式和主动模式.(具体查另外资料) 在JAVA中将FTPClient设置为 ...

  8. 【python】下载网络文件到本地

    # 下载网络图片文件到本地 import urllib.request rsp=urllib.request.urlopen("http://n.sinaimg.cn/ent/transfo ...

  9. java 下载网络文件

    1.FileUtils.copyURLToFile实现: import java.io.File; import java.net.URL; import org.apache.commons.io. ...

随机推荐

  1. django有什么CMS比较好用?哪个好?

    这个网站有目前在电子商务领域流行的django cms的横向对比表格,可以看看 https://djangopackages.org/grids/g/ecommerce/ 从结果上来看,django- ...

  2. UE4 Slate控件之TreeView 使用例子(一)

    TreeView例子 先从Contruct中往子Slot添加Widget,先声明指向STreeView的指针,后续方便进行视图的一些操作 TSharedPtr<STreeView<TSha ...

  3. XCTF-ics-05(文件包含+preg_replace函数/e修正符下的代码执行漏洞)

    记一道preg_replace函数/e模式下的代码执行漏洞利用的题. 只有设备维护中心页面可以进入,页面没有什么可点击的,查看源代码,发现这里有个参数. 拼接到url,页面显示index,拼接/etc ...

  4. (1)用 if语句 区间判断

    /*此例子只做比喻演示*/ 1 #include <stdio.h> 2 int main() 3 { 4 5 int p; 6 scanf("%d",&p); ...

  5. Salesforce Integration 概览(五) Remote Call-In(远程操作 外部->salesforce)

    本篇参考:https://resources.docs.salesforce.com/sfdc/pdf/integration_patterns_and_practices.pdf 本篇博客介绍 Re ...

  6. JAVA基础语法:常用功能符以及循环结构和分支结构(转载)

    3.JAVA基础语法:常用功能符以及循环结构和分支结构 1.常用功能符 注释 ("文字"是被注释的部分) //文字 单行注释 /文字/ 多行注释 算术运算符 + - * / / 整 ...

  7. Notes about multiboot usb creator

    U盘上的多系统启动工具,Windows上YUMI比较好,Ubuntu上MultiSystem用法复杂,unetbootin是另外一款,需要安装p7zip(apt-get install p7zip-f ...

  8. 让Dev支持C++11特性

    如果你使用的是 Dev-C++ ,忘记了在设置中包含 -std=c++11是无法让Dev支持C++11特性的,导致一些C++11 中的好用的函数可能会产⽣生编译⽆无法通过的情况. 这时候你有两个方法 ...

  9. nc基本操作&反弹shell

    一.nc简介 nc 被称为瑞士军刀netcat ,所做的就是在两台电脑之间建立链接,并返回两个数据流. 可运行在TCP或者UDP模式,添加参数 -u 则调整为UDP,默认为TCP 即可用在window ...

  10. SpringBoot 整合 SpringSecurity 梳理

    文档 Spring Security Reference SpringBoot+SpringSecurity+jwt整合及初体验 JSON Web Token 入门教程 - 阮一峰 JWT 官网 Sp ...