2012-01-20 10 views
18

Java 7 ve NIO 2 kullanarak eşzamansız bir sunucu yazmak istiyorum.Bağlantıları kabul etmek için AsynchronousServerSocketChannel'i nasıl kullanmalıyım?

Ancak AsynchronousServerSocketChannel'u nasıl kullanmalıyım?

E.g. Beraber başlıyorsa: Ben server.accept() yaptığınızda o çağrı asenkron çünkü

final AsynchronousServerSocketChannel server = 
    AsynchronousServerSocketChannel.open().bind(
     new InetSocketAddress(port)); 

Ardından, program sonlanır. Ve eğer bu kodu sonsuz bir döngüye koyarsam, AcceptPendingException atılır.

AsynchronousServerSocketChannel'u kullanarak basit bir eşzamansız sunucu nasıl yazılır? Eğer aynı iş parçacığı yapacak başka bir şey varsa

import java.io.IOException; 
import java.net.InetSocketAddress; 
import java.nio.channels.AsynchronousServerSocketChannel; 
import java.nio.channels.AsynchronousSocketChannel; 
import java.nio.channels.CompletionHandler; 

public class AsyncServer { 

    public static void main(String[] args) { 
     int port = 8060; 
     try { 
      final AsynchronousServerSocketChannel server = 
        AsynchronousServerSocketChannel.open().bind(
          new InetSocketAddress(port)); 

      System.out.println("Server listening on " + port); 

      server.accept("Client connection", 
        new CompletionHandler<AsynchronousSocketChannel, Object>() { 
       public void completed(AsynchronousSocketChannel ch, Object att) { 
        System.out.println("Accepted a connection"); 

        // accept the next connection 
        server.accept("Client connection", this); 

        // handle this connection 
        //TODO handle(ch); 
       } 

       public void failed(Throwable exc, Object att) { 
        System.out.println("Failed to accept connection"); 
       } 
      }); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 
+0

İstemci-sunucu uygulaması için özel olarak ise Netty çerçevesini kullanabilirsiniz gibi mandalını. Ayrıca java NIO kullanır. Sunucunun kolay ve hızlı bir şekilde gelişmesidir. http://netty.io/ –

+3

@Optimus üzerinden ilerleyin: Netty'yi biliyorum ama bu soruyla alakalı değil. – Jonas

cevap

9

kullanmak istiyorsunuz başka bir şey yapmıyorlar.

Dişin sonlanmasını önlemek için basit (ama çirkin) bir yol, iş parçacığı kesilene kadar basitçe döngüdür.

// yes, sleep() is evil, but sometimes I don't care 
while (true) { 
    Thread.sleep(1000); 
} 

Bir temizlikçi yolu AsynchronousChannelGroup kullanmaktır. Örneğin:

AsynchronousChannelGroup group = AsynchronousChannelGroup.withThreadPool(Executors 
      .newSingleThreadExecutor()); 
AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open(group).bind(
      new InetSocketAddress(port)); 

// (insert server.accept() logic here) 

// wait until group.shutdown()/shutdownNow(), or the thread is interrupted: 
group.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS); 

Sen melodi ipler nasıl ele alındığını, daha fazla bilgi için AsynchronousChannelGroup API docs görebilirsiniz.

+4

'// evet, uyu() kötülüktür, ama bazen umrumda değil umurumda olmalısınız. –

+4

Heh. _ugly_ ve _evil_ adını verdiysem ve daha güzel bir yol göstersem de, muhtemelen uyku() çağrısı nedeniyle, downvotes almayı sürdürün. Bu oldukça dogmatik görünüyor. :-) – Soulman

3

kullanma asenkron kabul yararlıdır:

İşte (JavaDoc'u örneğin benzer) benim tam örnektir. size durumda, çalışması gerekir daha bağlantıları kabul etmek için tamamlanan callback'inde dan() kabul çağırarak, bu yüzden Sen doğru yolda olan

while(true) { 
    AsynchronousSocketChannel socket = server.accept().get(); 
    System.out.println("Accepted " + socket); 
    socket.close(); 
} 
+0

Future.get() bekler ... –

+0

@gnarly Bunu yapar, ancak accept() her seferinde farklı bir Gelecek döndürür. –

+0

Benim örneğim, ['AsynchronousServerSocketChannel'] amacını ortadan kaldıran bir engelleme sunucusudur (http://docs.oracle.com/javase/7/docs/api/java/nio/channels/AsynchronousServerSocketChannel.html) . –

2

Başka bir seçenek, ana yönteminizin geri dönmeden önce bir sinyal beklemesini sağlamaktır. Sonra bir çeşit harici kapatma komutunuz varsa, sadece sinyali bildirirsiniz ve ana iplik kapanır. Kullanım geri sayım

private static final Object shutdownSignal = new Object(); 

public static void main(String[] args) { 

    ... 

    synchronized (shutdownSignal) { 
     try { 
      shutdownSignal.wait(); 
     } 
     catch (InterruptedException e) { 
      // handle it! 
     } 
    } 
} 
0

Aşağıdaki örnekte

final AsynchronousServerSocketChannel serverChannel = AsynchronousServerSocketChannel.open(); 
    InetSocketAddress address = new InetSocketAddress(port); 
    serverChannel.bind(address); 
    final CountDownLatch latch = new CountDownLatch(1); 
    serverChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Object>() { 
@Override 
     public void completed(final AsynchronousSocketChannel channel, Object attachment) { 
      serverChannel.accept(null, this); 
         } 

}); 
try { 
     latch.await(); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
     Thread.currentThread().interrupt(); 
    }