Java 插座打开管道,但不打开';别关上它
我正在监听一个套接字,并使用了readLine()函数。 如果我看到程序打开的文件描述符的数量,我会看到当我调用readLine()函数时,有东西打开了两个文件描述符(管道)。(可以在/proc//fd中看到) 如果发生套接字超时异常,即使在关闭缓冲读取器之后,管道仍保持打开状态。 如何关闭它 这是我的节目:Java 插座打开管道,但不打开';别关上它,java,linux,sockets,pipe,bufferedreader,Java,Linux,Sockets,Pipe,Bufferedreader,我正在监听一个套接字,并使用了readLine()函数。 如果我看到程序打开的文件描述符的数量,我会看到当我调用readLine()函数时,有东西打开了两个文件描述符(管道)。(可以在/proc//fd中看到) 如果发生套接字超时异常,即使在关闭缓冲读取器之后,管道仍保持打开状态。 如何关闭它 这是我的节目: import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.InetSocketAdd
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.channels.SocketChannel;
import java.util.StringTokenizer;
// Test case code for file descriptor leak.
// The following should produce somewhere near 150 sockets in CLOSE_WAIT state.
// The problem appears to be in sun.nio.ch.SocketAdapter.SocketInputStream.read(ByteBuffer);
public class TestClose implements Runnable {
public static final String SMTP_HOSTNAME = "10.10.10.59";
public void run()
{
InetSocketAddress sockAddr = new InetSocketAddress(SMTP_HOSTNAME, 5269);
SocketChannel sChannel = null;
Socket socket = null;
String result = null;
BufferedReader lineRdr = null;
InputStreamReader is = null;
try
{
sChannel = SocketChannel.open();
sChannel.socket().connect(sockAddr);
sChannel.socket().setSoTimeout(20000);
socket = sChannel.socket();
is = new InputStreamReader(socket.getInputStream());
lineRdr = new BufferedReader(is);
do
{
// before performing the first readline the channel is unregistered
System.err.println("before first readline: isOpen = "+sChannel.isOpen()+" isRegistered="+sChannel.isRegistered());
result = lineRdr.readLine();
System.err.println("<- "+result);
// after performing it is registered.
System.err.println("after first readline: isOpen = "+sChannel.isOpen()+" isRegistered="+sChannel.isRegistered());
} while(result != null && result.length() > 0 && result.matches("^[1-5][0-9]{2}-"));
if(result == null || result.length() == 0)
{
System.err.println("Received truncated response from SMTP server " + sockAddr.getHostName());
return;
}
// Tokenize the last line result
//
StringTokenizer t = new StringTokenizer(result);
int rc = Integer.parseInt(t.nextToken());
if(rc != 220) return;
//
// Send the QUIT command causing the server side to close its end of the connection
//
String cmd = "QUIT\r\n";
socket.getOutputStream().write(cmd.getBytes());
System.err.println("-> "+cmd);
do
{
result = lineRdr.readLine();
System.err.println("<- "+result);
} while(result != null && result.length() > 0 && result.matches("^[1-5][0-9]{2}-"));
if(result == null || result.length() == 0)
{
System.err.println("Received truncated response from SMTP server " + sockAddr.getHostName());
return;
}
}
catch (Exception e) {
System.out.println("result "+result);
e.printStackTrace();
}
finally
{
try {
//socket.getInputStream().close();
lineRdr.close();
lineRdr = null;
is.close();
is = null;
System.err.println("before close: isOpen = "+sChannel.isOpen()+" isRegistered="+sChannel.isRegistered());
System.err.println("Closing SMTP socket channel "+sChannel);
System.err.println("channel.socket().isConnected = "+ sChannel.socket().isConnected());
System.err.println("channel.socket().isclose = "+ sChannel.socket().isClosed());
System.err.println("channel.socket().isConnected = "+ sChannel.socket().isConnected());
if (sChannel != null) {
if(sChannel.socket().isClosed()== false){
sChannel.socket().shutdownOutput();
sChannel.socket().close();
}
// sChannel.shutdownOutput();
sChannel.close();
System.err.println("Closed SMTP socket channel "+sChannel);
// The socket is still connected here.
System.err.println("channel.socket().isConnected = "+sChannel.socket().isConnected());
System.err.println("channel.socket().isclose = "+ sChannel.socket().isClosed());
}
}
catch (Exception e) {
System.err.println("Exception on close:");
e.printStackTrace();
}
}
return;
}
public static void main(String[] args) {
TestClose test = new TestClose();
while(true) {
for(int i = 0; i < 1; i++) {
// this bug seems only to appear if different threads are reading the channels
Thread thread = new Thread(test);
thread.start();
try {thread.join(); } catch(InterruptedException e) { }
}
System.err.println("Going to sleep.... run netstat -an | grep CLOSE_WAIT ");
try { Thread.sleep(10000); } catch(InterruptedException e) {}
}
}
}
导入java.io.BufferedReader;
导入java.io.InputStreamReader;
导入java.net.InetSocketAddress;
导入java.net.Socket;
导入java.nio.channels.SocketChannel;
导入java.util.StringTokenizer;
//文件描述符泄漏的测试用例代码。
//以下应在关闭等待状态下产生大约150个插座。
//问题出现在sun.nio.ch.SocketAdapter.SocketInputStream.read(ByteBuffer)中;
公共类TestClose实现可运行{
公共静态最终字符串SMTP_HOSTNAME=“10.10.10.59”;
公开募捐
{
InetSocketAddress sockAddr=新的InetSocketAddress(SMTP_主机名,5269);
SocketChannel sChannel=null;
套接字=空;
字符串结果=null;
BufferedReader lineRdr=null;
InputStreamReader为空;
尝试
{
sChannel=SocketChannel.open();
sChannel.socket().connect(sockAddr);
sChannel.socket().setSoTimeout(20000);
socket=sChannel.socket();
is=新的InputStreamReader(socket.getInputStream());
lineRdr=新的缓冲读取器(is);
做
{
//在执行第一条读线之前,取消注册通道
System.err.println(“在第一个读取行之前:isOpen=“+sChannel.isOpen()+”isRegistered=“+sChannel.isRegistered());
结果=lineRdr.readLine();
System.err.println(“+cmd”);
做
{
结果=lineRdr.readLine();
System.err.println(“
我看到readLine()函数打开了两个文件描述符
(管道)
是,在socketTimeout设置为非零值后,SocketInputStream开始在readLine()
中使用非阻塞读取,并且可以(如果socket中还没有输入)为每个读取线程打开两个管道
如果发生套接字超时异常,即使在关闭缓冲
读卡器,管道仍然打开。我如何关闭它
您不必这样做,在您的情况下,当选择器(保存文件描述符ID)打开时,管道将在下一次GC后关闭将由sun.misc.Cleaner关闭。Cleaner类基于,其清理在ReferenceHandler线程中执行。因此,更准确的说法是套接字打开管道。Selector
打开管道,Selector
实例通过SelectorProvider.openSelector()创建
,而Socket
包含了SelectorProvider
的实例。但是我认为说套接字打开管道是不正确的。
。无论如何,我认为这是不必要的信息,因为很多细节都不清楚。在回答中,我指的是SocketAdaptor.SocketInputStream
决定创建选择器(并以这种方式打开管道)。此外,我还描述了取决于它将这样做的条件。在此之后,我回答了问题。我希望这是有帮助的。