2012-10-26 1 views
4

java 7 nio2를 사용하여 비동기 소켓 서버를 작성했습니다.Java7 비동기 NIO2 서버에서의 연결 거부

다음은 서버의 스니퍼입니다. 여기

public class AsyncJava7Server implements Runnable, CounterProtocol, CounterServer{ 
    private int port = 0; 
    private AsynchronousChannelGroup group; 
    public AsyncJava7Server(int port) throws IOException, InterruptedException, ExecutionException { 
     this.port = port; 
    } 

    public void run() { 
     try { 
      String localhostname = java.net.InetAddress.getLocalHost().getHostName(); 
      group = AsynchronousChannelGroup.withThreadPool(
       Executors.newCachedThreadPool(new NamedThreadFactory("Channel_Group_Thread"))); 

      // open a server channel and bind to a free address, then accept a connection 
      final AsynchronousServerSocketChannel asyncServerSocketChannel = 
          AsynchronousServerSocketChannel.open(group).bind(
           new InetSocketAddress(localhostname, port)); 

      asyncServerSocketChannel.accept(null, 
       new CompletionHandler <AsynchronousSocketChannel, Object>() { 
          @Override 
          public void completed(final AsynchronousSocketChannel asyncSocketChannel, 
             Object attachment) { 
            // Invoke simple handle accept code - only takes about 10 milliseconds. 
            handleAccept(asyncSocketChannel); 
            asyncServerSocketChannel.accept(null, this); 
      } 
          @Override 
          public void failed(Throwable exc, Object attachment) { 
           System.out.println("***********" + exc + " statement=" + attachment); 
      } 
       }); 

public class AsyncJava7Client implements CounterProtocol, CounterClientBridge { 
    AsynchronousSocketChannel asyncSocketChannel; 

    private String serverName= null; 
    private int port; 
    private String clientName; 

    public AsyncJava7Client(String clientName, String serverName, int port) throws IOException { 
     this.clientName = clientName; 
     this.serverName = serverName; 
     this.port = port; 
    } 

    private void connectToServer() { 
     Future<Void> connectFuture = null; 
     try { 
      log("Opening client async channel..."); 
      asyncSocketChannel = AsynchronousSocketChannel.open(); 

      // Connecting to server 
      connectFuture = asyncSocketChannel.connect(new InetSocketAddress("Alex-PC", 9999)); 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
      throw new RuntimeException(ex); 
     } 
     // open a new socket channel and connect to the server 
     long beginTime = 0; 
     try { 
      // You have two seconds to connect. This will throw exception if server is not there. 
      beginTime = System.currentTimeMillis(); 
      Void connectVoid = connectFuture.get(15, TimeUnit.SECONDS); 
     } catch (Exception ex) { 
      //EXCEPTIONS THROWN HERE AFTER ABOUT 150 CLIENTS 
      long endTime = System.currentTimeMillis(); 
      long timeTaken = endTime - beginTime; 
      log("************* TIME TAKEN=" + timeTaken); 
      ex.printStackTrace(); 
      throw new RuntimeException(ex); 
     } 
} 

나는 클라이언트를 발사 시험이 ... 연결을 시도하는 클라이언트 코드의 조각이다.

@Test 
public void testManyClientsAtSametime() throws Exception { 
    int clientsize = 150; 
    ScheduledThreadPoolExecutor executor = 
      (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(clientsize + 1, 
       new NamedThreadFactory("Test_Thread")); 
    AsyncJava7Server asyncJava7Server = startServer(); 
    List<AsyncJava7Client> clients = new ArrayList<AsyncJava7Client>(); 
    List<Future<String>> results = new ArrayList<Future<String>>(); 

    for (int i = 0; i < clientsize; i++) { 
     // Now start a client 
     final AsyncJava7Client client = 
       new AsyncJava7Client("client" + i, InetAddress.getLocalHost().getHostName(), 9999); 
     clients.add(client); 
    } 

    long beginTime = System.currentTimeMillis(); 
    Random random = new Random(); 
    for (final AsyncJava7Client client: clients) { 
     Callable<String> callable = new Callable<String>() { 
      public String call() { 
       ... 
       ... invoke APIs to connect client to server 
       ... 
       return counterValue; 
      } 
    }; 

    long delay = random.nextLong() % 10000; // somewhere between 0 and 10 seconds. 
    Future<String> startClientFuture = executor.schedule(callable, delay, TimeUnit.MILLISECONDS); 
    results.add(startClientFuture); 
} 

약 100 개의 클라이언트에서 작동합니다. 약 140+에서 클라이언트에 예외가 발생합니다. 연결하려고 할 때입니다. 예외 : java.util.concurrent.ExecutionException : java.io.IOException : 원격 컴퓨터가 네트워크 연결을 거부했습니다.

내 테스트는 Windows 7을 실행하는 단일 랩톱에서 수행됩니다. 폭탄이 터지면 TCP 연결을 점검하고 약 500 - 600 개의 연결을 확인합니다. 4,000 개의 TCP 연결을 처리 할 수있는 유사한 JDK 1.0 java.net 소켓 프로그램이 있습니다.

예외적 인 사항이나 서버에서의 위험한 부분은 없습니다.

나는 여기서 무엇이 잘못 될 수 있는지를 놓치고 있습니다. 어떤 아이디어?

+0

제대로 연결을 닫지 않았습니까? 즉, 방금 컴퓨터를 다시 시작한 경우와 테스트를 10 번 실행 한 경우의 한계가 140 정도입니까? 시험을 계속 실행하면 그 한도가 떨어지나요? – assylias

답변

4

백 로그 제한을 허용하는 bind의 형식을 사용하고 더 높은 번호로 설정하십시오. 예 :

  final AsynchronousServerSocketChannel asyncServerSocketChannel = 
         AsynchronousServerSocketChannel.open(group).bind(
          new InetSocketAddress(localhostname, port), 1000); 

기본적으로 win7 구현 제한이 무엇인지는 모르지만 연결을 거부 할 수 있습니다.

+1

잘 했어. 기본적으로 제한은 50 개입니다. 솔루션이 효과적이었습니다. 감사. – dublintech

+0

@dublintech : 빠른 질문 - 어디에서 기본 한도 인 50을 찾았습니까? 나는 훑어 보았지만 그것을 보지 못했다. – philwb

+0

실험으로. 귀하의 게시물 전에는 50 이었지만 솔루션을 알지 못했습니다. – dublintech

관련 문제