2012-02-23 87 views
1

我與NIO今天早些時候亂搞和numClients了(我的電腦〜2500)越大,我開始收到以下異常:Socket編程與NIO

java.net.ConnectException: Connection refused: no further information 
    at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method) 
    at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:701) 
    at SocketInformationExceptionTest.run(SocketInformationExceptionTest.java:49) 
    at java.lang.Thread.run(Thread.java:722) 

從這個代碼:

import java.io.IOException; 
import java.net.InetAddress; 
import java.net.InetSocketAddress; 
import java.nio.channels.ClosedChannelException; 
import java.nio.channels.SelectionKey; 
import java.nio.channels.Selector; 
import java.nio.channels.ServerSocketChannel; 
import java.nio.channels.SocketChannel; 
import java.util.Iterator; 
import java.util.concurrent.BlockingQueue; 
import java.util.concurrent.LinkedBlockingQueue; 

public class SocketInformationExceptionTest implements Runnable { 
    private static interface Request { 
     public void process(Selector sel); 
    } 

    private final Selector selector; 
    private final BlockingQueue<Request> requests = new LinkedBlockingQueue<>(); 

    public SocketInformationExceptionTest() throws IOException { 
     selector = Selector.open(); 
    } 

    public void addRequest(Request r) { 
     requests.add(r); 
     selector.wakeup(); 
    } 

    @Override 
    public void run() { 
     while (true) { 
      while (!requests.isEmpty()) { 
       Request r = requests.poll(); 
       r.process(selector); 
      } 
      try { 
       selector.select(); 

       Iterator<SelectionKey> itr = selector.selectedKeys().iterator(); 
       while (itr.hasNext()) { 
        SelectionKey key = itr.next(); 
        itr.remove(); 

        if (key.isValid()) { 
         if (key.isAcceptable()) { 
          ((ServerSocketChannel) key.channel()).accept(); 
         } else if (key.isConnectable()) { 
          ((SocketChannel) key.channel()).finishConnect(); 
         } 
        } 
       } 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

    public static void main(String[] args) throws IOException { 
     int numClients = 2500; 

     SocketInformationExceptionTest test = new SocketInformationExceptionTest(); 
     new Thread(test).start(); 

     final ServerSocketChannel server = ServerSocketChannel.open().bind(
       new InetSocketAddress(1234)); 
     server.configureBlocking(false); 

     test.addRequest(new Request() { 
      @Override 
      public void process(Selector sel) { 
       try { 
        server.register(sel, SelectionKey.OP_ACCEPT); 
       } catch (ClosedChannelException e) { 
        e.printStackTrace(); 
       } 
      } 
     }); 

     for (int x = 0; x < numClients; x++) { 
      final SocketChannel socket = SocketChannel.open(); 
      socket.configureBlocking(false); 
      socket.connect(new InetSocketAddress(InetAddress.getLocalHost(), 
        1234)); 

      test.addRequest(new Request() { 
       @Override 
       public void process(Selector sel) { 
        try { 
         socket.register(sel, SelectionKey.OP_CONNECT); 
        } catch (ClosedChannelException e) { 
         e.printStackTrace(); 
        } 
       } 
      }); 
     } 

     System.exit(0); 
    } 
} 

這種情況下,我的電腦無法跟上請求,或者是在這裏發生的更險惡的事情?谷歌搜索沒有任何用處。

可能相關的信息:
Java版本 「1.7.0_02」
的Java(TM)SE運行時環境(建立1.7.0_02-B13)
的HotSpot的Java(TM)客戶端虛擬機(建設22.0 - B10,混合模式,共享)

32位Windows 7家庭高級版SP 1
AMD炫龍M500雙核2.20 GHz的
2.00 GB內存
瑞昱RTL8191SE無線網絡的802.11n PCI-E網卡

回答

3

您在連續打開數千個客戶端連接時沒有中介休眠,因此您可能會溢出ServerSocketChannel的監聽積壓隊列,此時Windows開始拒絕連接。無論您使用這種技術進行測試,它都不是一個有效的測試,因爲您(a)捱餓運行的服務器線程並且(b)可能將耗盡出站端口空間,此時您將如果你可以超越你目前的問題,就可以在connect()上獲取BindExceptions。

此外,您並未關閉您的連接和接受的頻道,只是永遠積累它們。所以當你到達numClients = 2500時,你有5000個插座打開,你知道嗎?