HttpURLConnection.getInputStream() 挂起并且永远不会完成

Posted

技术标签:

【中文标题】HttpURLConnection.getInputStream() 挂起并且永远不会完成【英文标题】:HttpURLConnection.getInputStream() hangs and never finishes 【发布时间】:2018-09-27 17:27:43 【问题描述】:

我正在尝试使用以下代码从 JSON 端点获取令牌:

public class FetchToken extends AsyncTask<String, Void, Void> 
    String data = "";
    String token = "";

    public TokenDelegate delegate = null;

    @Override
    protected Void doInBackground(String... identity) 
        try 
            if (identity.length == 1) 
                URL url = new URL(identity[0]);

                HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
                InputStream inputStream = httpURLConnection.getInputStream();
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                String line = "";

                while (line != null) 
                    line = bufferedReader.readLine();
                    data = data + line;
                

                JSONObject JO = new JSONObject(data);
                token = JO.get("token").toString();
            
         catch (MalformedURLException e) 
            e.printStackTrace();
         catch (IOException e) 
            e.printStackTrace();
         catch (JSONException e) 
            e.printStackTrace();
        

        return null;
    

    @Override
    protected void onPostExecute(Void aVoid) 
        Log.d("token", token);
        //delegate.processFinish(token);
        super.onPostExecute(aVoid);
    

我尝试在每一行之后打印到调试日志,似乎InputStream inputStream = httpURLConnection.getInputStream(); 行永远不会完成,其余代码也不会执行。但是,这发生在 AsyncTask 内部,并且该 AsyncTask 的 onPostExecute 方法正在触发,就好像任务已经完成一样,但它看起来好像已经完成了。

似乎没有执行任何 catch 块,当我检查 android Profiler 中的网络面板时,请求说它没有传回任何东西。但是,在浏览器中访问 JSON 端点会使一切恢复正常。

希望有人知道问题可能是什么。我试图用谷歌搜索无济于事。如果需要更多信息,请告诉我。谢谢。

【问题讨论】:

the onPostExecute method of that AsyncTask is firing - 那么httpURLConnection.getInputStream() 正在工作,如果(identity.length == 1) 因为这是一个阻塞调用,你确定你没有捕获异常并返回null - 检查logcat ?还要确保关闭 finally 块中的流 你找到正确的解决方案了吗? 就我而言,这是因为我的模拟器无法连接到互联网 【参考方案1】:

您很可能希望设置超时以确保在外部资源无法及时获得时连接失败。这些值以毫秒为单位,例如连接和读取的 5 秒超时将是:

 HttpURLConnection conn = ...
 conn.setConnectTimeout(5000);
 conn.setReadTimeout(5000);

默认情况下,超时设置为0,根据setConnectTimeout(),这意味着:

零超时被解释为无限超时。

【讨论】:

感谢您的建议。不幸的是,这并没有解决问题。当我在浏览器中访问资源时,它确实比超时恢复得更快。【参考方案2】:

InputStream inputStream = httpURLConnection.getInputStream(); 行从未完成,因为它正在抛出 java.security.cert.CertPathValidatorException。错误没有被记录,因为我没有在我的 try / catch 块中捕捉到这种类型的错误。

【讨论】:

【参考方案3】:

查看下面的代码并相应地修改您的代码。

1) 如果方法是 GET,则数据或标头可以为空。

示例用法

 url = <some url>
 Map<String, String> headers = new HashMap<String, String>();       
 headers.put("Content-Type", "application/json");       
 headers.put("Accept", "application/json");

a) 获取:

invokeHTTPRequest(url, "GET", headers, null);

b) 发布

Student st = new Student();
Gson gson = new Gson();
String jsonReqData = gson.toJson(st);
String resp = invokeHTTPRequest3(url, "POST", headers,  jsonReqData);

public static String invokeHTTPRequest(String urlString, String method, Map headers,String data)

    URL url = null;
    try 
        url = new URL(urlString);
        HttpURLConnection conn = null;
        conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod(method);
        conn.setConnectTimeout(10000);
        conn.setReadTimeout(10000);

        if (headers != null) 
            for (Map.Entry<String, String> header : headers.entrySet()) 
                conn.setRequestProperty(header.getKey(), header.getValue());
            
        



        if (data != null) 
            byte[] postDataBytes = data.toString().getBytes();
            conn.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length));
            conn.setDoOutput(true);
            conn.getOutputStream().write(postDataBytes);

        

        BufferedReader rd = null;

        if(conn.getResponseCode() == 200)
            rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        
        else
            rd = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
        

        StringBuilder result = new StringBuilder();

        String line;
        while ((line = rd.readLine()) != null) 
            result.append(line);
        
        rd.close();


        return result.toString();

     catch (Exception e) 
        //handle exception here
    


【讨论】:

【参考方案4】:

您忘记在HttpUrlConnection 上拨打connect

HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.connect();
InputStream inputStream = httpURLConnection.getInputStream();

【讨论】:

用 .connect() 添加行似乎不能解决问题。 其实connect() 是不需要的。只需调用url.openConnection(); 就足够了 是的,我忘了 getInputStream() 会强制 connect() :/

以上是关于HttpURLConnection.getInputStream() 挂起并且永远不会完成的主要内容,如果未能解决你的问题,请参考以下文章