为什么创建socketchannels比最大打开文件更多?

时间:2015-05-25 09:46:37

标签: linux sockets nio

在linux中,Socket也是一个文件,所以如果一次存在太多套接字且超过最大打开文件,它将抛出异常:

java.net.SocketException: Too many open files
at sun.nio.ch.Net.socket0(Native Method)
at sun.nio.ch.Net.socket(Net.java:423)
at sun.nio.ch.Net.socket(Net.java:416)
at sun.nio.ch.SocketChannelImpl.<init>(SocketChannelImpl.java:104)
at sun.nio.ch.SelectorProviderImpl.openSocketChannel(SelectorProviderImpl.java:60)
at java.nio.channels.SocketChannel.open(SocketChannel.java:142)

直到现在我能理解,但我对下面的现象感到有些困惑。 我在终端执行了以下命令,找到最大打开文件号:

$ ulimit -n
1024

但实际上我通过以下代码创建了大约4091个套接字(SocketChannel):

while(true) {   
    new Thread(new Runnable() {
        public void run() {
            //...
            try {
                SocketChannel scChannel = SocketChannel.open();
                scChannel.connect(new InetSocketAddress(hostname, port));
                ByteBuffer buffer = ByteBuffer.allocate(1024);
                scChannel.read(buffer);
            } catch (IOException e) {
                //...
            }                   
        }
    }).start(); 
}

从控制台我知道,直到它创建4091 socketChannel,然后它抛出异常:

Start client 4091
java.net.SocketException: Too many open files

4091超过1024,为什么会这样? ulimit的结果不是最大打开文件的实际数量吗?

1 个答案:

答案 0 :(得分:1)

根据上午的建议,我检查了jvm是否改变了ulimit。我发现jvm确实做了些什么。我用java代码执行了ulimit命令,如下所示:

ProcessBuilder pBuilder = new ProcessBuilder("sh","-c","ulimit -n");
Process p = pBuilder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = reader.readLine();
while(line!=null){
    System.out.println(line);
    line = reader.readLine();
}  

输出为4096 - 与终端输出不同。 但我不知道jvm如何以及何时何地改变了ulimit值。