1

我在 Tomcat 上运行一个 Web 应用程序。我的应用程序连接到其他 Web 服务来满足来自客户端的请求。有时我在打开 URL 连接时收到 java.net.UnknownHostException,然后有时我开始收到 java.net.SocketException: Too many open files。我的服务器停止进一步接受连接。请指导。

String  response;
    HttpURLConnection conn = null;
BufferedReader rd = null;
InputStream in = null;
try
{
    // Send data
    String urlStr = URL;
    URL url = new URL(urlStr);
    conn = (HttpURLConnection)url.openConnection();
    conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
    int contentLength = conn.getContentLength();
    //   System.out.println("content length 1" +  contentLength);
    if (contentLength <= 0)
    {
        InputStream in1 = (conn).getErrorStream();
        if (in1 != null)
        {
            in1.close();
        }
        conn.getInputStream().close();
        in = null;
        conn.disconnect();
        conn = null;
        return null;
    }
    in = conn.getInputStream();
    if (conn.getResponseCode() != 200)
    {
        InputStream in1 = (conn).getErrorStream();
        if (in1 != null)
        {
            in1.close();
        }
        conn.getInputStream().close();
        in = null;
        conn.disconnect();
        conn = null;
        in.close();
        in = null;
        return null;
    }
    // Get the response
    rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
    StringBuffer stringBuffer = new StringBuffer();
    String line = null;
    while ((line = rd.readLine()) != null)
    {
        stringBuffer.append(line);
    }
    response = stringBuffer.toString();
    System.out.println("full ads response = " + response);
}
catch (Exception ex)
{
    //   ex.printStackTrace();
}
finally
{
    try
    {
        if (conn != null)
        {
            InputStream in1 = (conn).getErrorStream();
            if (in1 != null)
            {
                in1.close();
            }
            conn.getInputStream().close();
            in = null;
            conn.disconnect();
            conn = null;
        }
        if (rd != null)
        {
            rd.close();
            rd = null;
        }
        if (in != null)
        {
            in.close();
            in = null;
        }
    }
    catch (Exception e)
    {
    }
}
return null;        
4

4 回答 4

2

UnknownHostException只是意味着您使用的 URL 指的是一个不存在的主机名,或者可能是该主机名的 DNS 记录或系统当时正在转换。

套接字泄漏可能是由您在下面的过多清理代码引起的,请参阅注释。

当您压制所有异常时,您对 Hades 没有希望找出问题所在。所以这是首先要解决的问题。永远不要忽略异常。记录它们。打印他们的堆栈跟踪。做一点事。

但是,您的代码也有许多其他问题:

HttpURLConnection conn = null;
BufferedReader rd = null;
InputStream in = null;
try
{
    // Send data
    String urlStr = URL;

这个变量是多余的。只需URL在下面使用。

    URL url = new URL(urlStr);
    conn = (HttpURLConnection)url.openConnection();
    conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");

到目前为止还可以。

    int contentLength = conn.getContentLength();
    //   System.out.println("content length 1" +  contentLength);
    if (contentLength <= 0)

检查零内容长度是非常不寻常的。这是检查错误的代理吗?我会简单地删除这个测试。

    {
        InputStream in1 = (conn).getErrorStream();
        if (in1 != null)
        {
            in1.close();
        }
        conn.getInputStream().close();
        in = null;
        conn.disconnect();
        conn = null;
        return null;
    }

以上都是多余的。您已经在 finally 块中拥有它。去掉它。

    in = conn.getInputStream();
    if (conn.getResponseCode() != 200)

现在这就是检查错误的方法。但是,您必须在调用getResponseCode() 之前调用,否则当您可能对响应代码 404 更感兴趣时getInputStream(),,后者可能会抛出。FileNotFoundException

    {
        InputStream in1 = (conn).getErrorStream();
        if (in1 != null)
        {
            in1.close();
        }
        conn.getInputStream().close();
        in = null;
        conn.disconnect();
        conn = null;
        in.close();
        in = null;
        return null;
    }

同样,以上所有内容都是多余的。您已经在 finally 块中拥有它。去掉它。

    // Get the response
    rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
    StringBuffer stringBuffer = new StringBuffer();
    String line = null;

的初始化line是多余的。变量在下一行中赋值。去掉它。

    while ((line = rd.readLine()) != null)
    {
        stringBuffer.append(line);
    }
    response = stringBuffer.toString();
    System.out.println("full ads response = " + response);
}
catch (Exception ex)

你应该只在这里赶上IOException

{
    //   ex.printStackTrace();

永远不要忽略异常。

}
finally
{
    try
    {
        if (conn != null)
        {
            InputStream in1 = (conn).getErrorStream();
            if (in1 != null)
            {
                in1.close();
            }

您不需要获取或关闭错误流。删除这一切。

            conn.getInputStream().close();
            in = null;

将此变量设置为 null 是没有意义的。它是一个局部变量,所以无论如何它都会超出范围。

            conn.disconnect();
            conn = null;

同上。

        }
        if (rd != null)
        {
            rd.close();
            rd = null;
        }

您已经关闭了输入流。这是多余的。删除此块。

        if (in != null)
        {
            in.close();
            in = null;
        }

您已经关闭了连接的输入流。这都是多余的。去掉它。

    }
    catch (Exception e)
    {
    }

同样,您应该只在IOException这里捕获,并且您不应该忽略错误。就我个人而言,我会使用 throw 方法IOException并且根本没有任何 catch 块。返回 null 对调用者来说不是很有用。他通常最好确切地知道出了什么问题,这样他就可以就如何处理它做出有用的决定。

}
return null;        
于 2013-04-10T05:43:40.827 回答
1

我最近在尝试与无法访问的 URL 建立大量连接时遇到了这个问题。连接会因 UnknownHostException 而失败,但最终会因 java.net.SocketException: Too many open files 而失败。

问题是,底层本机套接字句柄是由 HttpURLConnection 创建的。似乎直到对象被垃圾收集之后才释放此句柄。就我而言,没有足够的内存用于触发垃圾收集。如果 GC 从未运行,则不会释放本机句柄。

我的解决方案是在获取 UnknownHostExceptions 时定期调用 System.gc()。我知道这看起来像是一个杂物,但它起作用了,底层的本机句柄被释放了,问题就消失了。

于 2020-10-14T00:31:44.807 回答
0

尝试增加您的 linux 服务器打开文件限制以修复java.net.SocketException: Too many open files. 最大文件的限制存储在linux中的这个文件中:

/proc/sys/fs/file-max

要检查当前打开的文件,您可以使用:

lsof

检查号码。打开文件,使用:

lsof | wc -l

此外,除了 conn.disconnect() 之外,关闭您的连接 conn.close()。确保你也关闭了 inputreader。所有此类关闭都应该在 finally 块中,以便在出现任何异常时也关闭连接。

于 2013-04-10T05:10:42.517 回答
0

你是在windows还是linux上运行?检查这篇文章,希望它有所帮助:http ://edmund.haselwanter.com/en/blog/2009/03/13/tomcat-too-many-open-files/

于 2013-04-10T05:10:58.580 回答