Stream.Read()无限挂起问题

我正在下载网络文件,用的httpwebrequest GetResponse GetResponseStream,整个都能跑通
唯一的问题是 如果服务器不响应我了,就会在stream.read处无限挂起,
无论是设置httpwebrequest 的ReadWriteTimeout (所有能设置的timeout我都设置过了 不生效 会在read处卡住 等待服务器反应)
还是设置stream的ReadTimeout和WriteTimeout都无效,就是一直获取到数据为止,断连的话read就返回0了,但服务器也不断连,就一直拖着。
20分钟也不断,就一直在等待。资源是别人服务器的,所以无法调整服务器端,所以这种情况该怎么处理,很头疼。
有解决方法的话我亲测可用后会给分。

不好意思,刚刚我回答多个问题回答混了(抱歉!)
你试试多线程解决方法:(我不保证成功)
基本思路是:
使用多线程的方法,开启一个新的线程来执行stream.read(),并设置线程的超时时间。
如果线程超时,就会自动结束线程,从而解决无限挂起的问题。

再用一个线程监视就行了。

可以试试以下方法
1,用线程监听,然后用,HttpWebRequest.Abort()结束请求
2,使用HttpWebRequest.BeginGetRequestStream(AsyncCallback, Object)异步请求
3,使用read前用CanRead判断一下,用CanSeek判断一下,CanTimeout,CanWrite也可以试试,或者设置一下steam的ReadTimeout和WriteTimeout
4,使用Read(Byte[], Int32, Int32)每次读取指定的字节,循环读取,这样就可以在循环里增加一个判断,比如循环次数太多,判断返回的文件是恶意的,就终止读取。

您好,我是有问必答小助手,您的问题已经有小伙伴帮您解答,感谢您对有问必答的支持与关注!
PS:问答VIP年卡 【限时加赠:IT技术图书免费领】,了解详情>>> https://vip.csdn.net/askvip?utm_source=1146287632

摘自一篇实例的思路:


**做个总结,进行远程通信时,在客户程序中,线程在以下情况可能进入阻塞状态:**

请求与服务器建立连接时,即当线程执行Socket的带参数的构造方法,或执行Socket的connect()方法时,会进入阻塞状态,直到连接成功,此线程才从Socket的构造方法或connect()方法返回。
线程从Socket的输入流读入数据时,如果没有足够的数据,就会进入阻塞状态,直到读到了足够的数据,或者到达输入流的末尾,或者出现了异常,才从输入流的read()方法返回或异常中断。输入流中有多少数据才算足够呢?这要看线程执行的read()方法的类型:


 1. int read():只要输入流中有一个字节,就算足够。
 2. int read(byte[] buff):只要输入流中的字节数目与参数buff数组的长度相同就算足够。
 3. String readLine():只要输入流中有一行字符串,就算足够。值得注意的是InputStream类并没有readLine()方法,在过滤流BufferedReader类中才有此方法。

线程向Socket的输出流写一批数据时,可能会进入阻塞状态,等到输出了所有的数据,或者出现异常,才从输出流的write()方法返回或异常中断。
当调用Socket的setSoLinger()方法设置了关闭Socket的延迟时间,那么当线程执行Socket的close()方法时,会进入阻塞状态,直到底层Socket发送完所有剩余数据,或者超过了setSoLinger()方法设置的延迟时间,才从close()方法返回。
在服务器程序中,线程在以下情况可能会进入阻塞状态:

线程执行ServerSocket的accept()方法,等待客户的连接,直到接收到了客户连接,才从accept()方法返回。
线程从Socket的输入流读入数据时, 如果输入流没有足够的数据,就会进入阻塞状态。
线程向Socket的输出流写一批数据时,可能会进入阻塞状态,等到输出了所有的数据,或者出现异常,才从输出流的write()方法返回或异常中断。

###解决方案
---
1, 通过setTimeout可以解决问题
```java
//设置connection timeout为3秒
connection.setConnectionTimeout(3 * 1000)
//设置read timeout为5秒
connection.setReadTimeout(5 * 1000)



2,通过一个connection的监控线程,查询定时清除掉已经expired或者idle的链接。





<div class="se-preview-section-delimiter"></div>

```java
public static class IdleConnectionMonitorThread extends Thread {

    private final HttpClientConnectionManager connMgr;
    private volatile boolean shutdown;

    public IdleConnectionMonitorThread(HttpClientConnectionManager connMgr) {
        super();
        this.connMgr = connMgr;
    }

    @Override
    public void run() {
        try {
            while (!shutdown) {
                synchronized (this) {
                    wait(5000);
                    // Close expired connections
                    connMgr.closeExpiredConnections();
                    // Optionally, close connections
                    // that have been idle longer than 30 sec
                    connMgr.closeIdleConnections(30, TimeUnit.SECONDS);
                }
            }
        } catch (InterruptedException ex) {
            // terminate
        }
    }

    public void shutdown() {
        shutdown = true;
        synchronized (this) {
            notifyAll();
        }
    }

}

为了避免在Stream.Read方法处无限挂起,可以使用HttpWebRequest.GetResponse方法的重载版本,它具有超时参数。例如:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Timeout = 10000; // 10 seconds
HttpWebResponse response = (HttpWebResponse)request.GetResponse();

这将设置请求的超时时间为10秒。如果服务器在10秒内未响应,则会引发超时异常。

此外,还可以使用WebException类的Status属性来检测超时。例如:

try
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
    request.Timeout = 10000; // 10 seconds
    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
}
catch (WebException ex)
{
    if (ex.Status == WebExceptionStatus.Timeout)
    {
        // The request timed out
    }
}


在调用 HttpWebRequest.GetResponse() 方法时,可以将其包装在 try-catch 语句中,并在捕获 WebException 异常时进行处理。WebException 异常表示在进行 HTTP 求时发生错误。可以使用 WebException.Status 属性检查具体的错误状态。

例如可以使用以下代码来处理服务器不响应的情况:

try
{
    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
    // 处理响应
}
catch (WebException ex)
{
    if (ex.Status == WebExceptionStatus.Timeout)
    {
        // 处理超时
    }
    else if (ex.Status == WebExceptionStatus.ConnectFailure)
    {
        // 处理连接失败
    }
    else
    {
        // 处理其他异常
    }
}

还可以使用 WebException.Response 属性获取服务器返回的响应,以便进一步处理。

此外还可以在创建 HttpWebRequest 对象时设置超时时间。例如使用 HttpWebRequest.Timeout 属性可以设置整个求的超时时间,使用 HttpWebRequest.ReadWriteTimeout 属性可以设置读写流的超时时间。

在调用 HttpWebRequest.GetResponse() 方法之前,还可以使用 HttpWebRequest.Abort() 方法中止求。
在调用 HttpWebRequest.GetResponse() 方法时,可以将其包装在 try-catch 语句中,并在捕获 WebException 异常时进行处理。WebException 异常表示在进行 HTTP 求时发生错误。可以使用 WebException.Status 属性检查具体的错误状态。

例如可以使用以下代码来处理服务器不响应的情况:

try
{
    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
    // 处理响应
}
catch (WebException ex)
{
    if (ex.Status == WebExceptionStatus.Timeout)
    {
        // 处理超时
    }
    else if (ex.Status == WebExceptionStatus.ConnectFailure)
    {
        // 处理连接失败
    }
    else
    {
        // 处理其他异常
    }
}

可以使用 WebException.Response 属性获取服务器返回的响应,以便进一步处理。

还可以在创建 HttpWebRequest 对象时设置超时时间。例如使用 HttpWebRequest.Timeout 属性可以设置整个求的超时时间,使用 HttpWebRequest.ReadWriteTimeout 属性可以设置读写流的超时时间。

在调用 HttpWebRequest.GetResponse() 方法之前,还可以使用 HttpWebRequest.Abort() 方法中止求。
望采纳。

NetworkStream.Read会挂起/阻止的原因是什么
借鉴下
https://qa.1r1g.com/sf/ask/487077881/