我在Tomcat上运行Web应用程序。我的应用程序连接到其他Web服务以满足客户端的请求。有时我在打开URL连接时得到java.net.UnknownHostException,然后有时我开始得到java.net.SocketException:打开的文件太多了。我的服务器停止接受连接。请指导。
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;
答案 0 :(得分:2)
UnknownHostException
只是表示您使用的URL是指不存在的主机名,或者可能是主机名的DNS记录或系统在该时刻处于转换状态。
套接字泄漏可能是由下面的过多清理代码引起的,请参阅注释。
当你压制所有异常时,你不会对哈迪斯有任何希望找出问题所在。所以这是第一件要解决的问题。永远不要忽视异常记录它们。打印堆栈跟踪。做点什么。
然而,您的代码还有许多其他问题:
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()
,然后调用getInputStream(),
,否则后者可能会在您对响应代码为404感兴趣时抛出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
,你不应该忽略错误。就个人而言,我会抛出方法IOException
并且根本没有任何catch块。返回null对调用者来说并不是很有用。他通常会更好地知道到底出了什么问题,这样他就可以做出有用的决定。
}
return null;
答案 1 :(得分:0)
尝试增加linux服务器打开文件限制以修复java.net.SocketException: Too many open files
。 max文件的限制存储在linux中的这个文件中:
/proc/sys/fs/file-max
要检查当前打开的文件,可以使用:
lsof
检查否。打开文件,使用:
lsof | wc -l
另外,除了conn.disconnect()之外,关闭你的连接conn.close()。确保您也关闭了inputreader。所有这些关闭都应该在finally块中,以便在出现任何异常时也关闭连接。
答案 2 :(得分:0)
你在Windows或Linux上运行吗?查看这篇文章,希望它有所帮助:http://edmund.haselwanter.com/en/blog/2009/03/13/tomcat-too-many-open-files/
答案 3 :(得分:0)
我最近在尝试与无法访问的URL建立大量连接时遇到了此问题。连接会因UnknownHostException而失败,但最终会因java.net.SocketException而失败:打开的文件太多。
问题是,底层的本机套接字句柄是由HttpURLConnection创建的。似乎直到对象被垃圾回收后才释放该句柄。就我而言,没有足够的内存来触发垃圾回收。如果GC从未运行,则不会释放本机句柄。
我的解决方案是在获取UnknownHostExceptions时定期调用System.gc()。我知道这似乎有点麻烦,但是它奏效了,底层的本机句柄被释放,问题消失了。