4

Java 7 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 を実行している 1 台のラップトップで行われました。爆発したとき、TCP 接続を確認すると、約 500 から 600 の接続がありますが、問題ありません。私は 4,000 の TCP 接続を処理できる同様の JDK 1.0 java.net ソケット プログラムを持っています。

サーバーで例外や怪しいものはありません。

だから私はここで何が間違っているのか途方に暮れています。何か案は?

4

1 に答える 1

4

bindバックログ制限を受け入れる形式を使用して、それをより高い数値に設定してみてください。例えば:

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

win7の実装制限がデフォルトで何であるかはわかりませんが、接続が拒否される原因となる可能性があります。

于 2012-11-02T22:48:01.300 に答える