今天在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. js hook

    //cookie hook (function () { 'use strict'; var cookie_cache = document.cookie; Object.defineProperty ...

  2. 在Java开发工具的project中使用相对路径

    1.在project中,相对路径的根目录是project的根文件夹,在此就是repathtest文件夹了.创建文件的写法是: File f = new File("src/com/lavas ...

  3. Sqli-labs 注入靶场(1-22)

    Sqli-labs靶场1-22 Sql注入的本质是代码和数据的未分离,导致用户的输入可以对数据库产生恶意的输入或输出. 本篇博客旨在通过Sqli-labs的第1-22关,详细的描述Sql注入的相关场景 ...

  4. PHP-Audit-Labs-Day1 - in_array函数缺陷

    函数缺陷原理分析 先看一段简单的源代码 class Challenge{ const UPLOAD_DIRECTORY = './solutions/'; private $file; private ...

  5. C++ 继承方式 //语法:class 子类 :继承方式 父类 //继承方式 三种: //1.公共继承 //2.保护继承 //3.私有继承

    1 //继承方式 2 //语法:class 子类 :继承方式 父类 3 //继承方式 三种: 4 //1.公共继承 5 //2.保护继承 6 //3.私有继承 7 8 #include <ios ...

  6. 大写字母与小写字母 相差 一个 空格 A = 65 a = 97 空格 = 32

    1 //大写字母与小写字母 相差 一个 空格 A = 65 a = 97 空格 = 32 2 3 #include <stdio.h> 4 int main() 5 { 6 7 char ...

  7. 物理机安装ESXi并优化部署虚拟机

    物理机配置 CPU,BIOS中启用虚拟化(VT-X) 内存和硬盘,内存尽量大.硬盘最好SSD,内存的大小和硬盘的速度直接决定了虚拟机运行的快慢 网络,至少一块千兆网卡(vSphere7.0版本以后支持 ...

  8. CYPEESS USB3.0程序解读之---同步FIFO(slaveFifoSync)

    上一篇文章解读了CYPRESS FX3的GPIO的操作过程,下面解读同步FIFO的一个例子(slaveFifoSync). *生产者,消费者. 1.首先看DMA的回调函数(cyu3dma.h): ty ...

  9. Go连接到Linux服务器进行操作-执行shell命令&&上传文件

    Go连接到Linux服务器进行操作 使用密码连接Linux服务器 package main import ( "fmt" "golang.org/x/crypto/ssh ...

  10. [ES6深度解析]12:Classes

    我们将讨论一个老问题:在JavaScript中创建对象的构造函数. 存在的问题 假设我们想要创建最典型的面向对象设计的示例:Circle类.假设我们正在为一个简单的Canvas库编写一个Circle. ...