2008-10-06 10 views
6

Bir SocketChannel engelleme üzerinde bir ObjectInputSteam ve ObjectOutputStream oluşturdu ve aynı anda okuma ve yazma çalışıyorum. (SelectableChannel#blockingLock() tarafından döndürülen nesne üzerinde bloklar)Java: Object (In | Out) putStreams ile bir blok SocketChannel üzerinde eşzamanlı okuma ve yazma mümkün mü?

socketChannel = SocketChannel.open(destNode); 
objectOutputStream = new ObjectOutputStream(Channels.newOutputStream(socketChannel)); 
objectInputStream = new ObjectInputStream(Channels.newInputStream(socketChannel)); 

Thread replyThread = new Thread("SendRunnable-ReplyThread") { 
    @Override 
    public void run() { 
     try { 
      byte reply = objectInputStream.readByte();//(A) 
      //..process reply 
     } catch (Throwable e) { 
      logger.warn("Problem reading receive reply.", e); 
     } 
    } 
}; 
replyThread.start(); 

objectOutputStream.writeObject(someObject);//(B) 
//..more writing 

Sorun hattı (B) 'deki yazma olduğu bloklar okuma kadar hattı (A)' da tamamlar: My kod aşağıdaki gibi bir şeydir. Ancak uygulama mantığı, tüm yazımlar tamamlanıncaya kadar okunmanın tamamlanmayacağını, dolayısıyla etkin bir çıkmaza sahip olduğumuzu belirtir. Eşzamanlı okuma ve yazmaların desteklendiğini söyleyen javadocs, javadocs derler. Eğer aynı anda InputStream ve OutputStream kullanmak istiyorsanız Ancak, o zaman ben FileChannel#transferTo(...)

cevap

1

performans avantajlarından alamaz

Socket socket = new Socket(); 
socket.connect(destNode); 
final OutputStream outputStream = socket.getOutputStream(); 
objectOutputStream = new ObjectOutputStream(outputStream); 
objectInputStream = new ObjectInputStream(socket.getInputStream()); 

: Ben normal Soket çözüm çalıştı

Öyle bir sorun yaşadı SocketChannel ile, kaynağa bakarak, SocketChannel.socket() öğesini çağırmanız ve akışları biraz farklı davrananlardan kullanmanız gerekir.

+0

socketChannel.socket(). Get (Out | In) putStream kullanmak için değiştirmeyi denedim, ancak fark yaratmadı. OutputStream daha önce olduğu gibi aynı türden görünüyor: Kanallar # newOutputStream (OutputStream) tarafından döndürülen anonim bir iç sınıf. –

+0

Bir alt sınıfa (test edilmemiş) geçiş yapması gereken InputStream. –

+4

* bugster denetler * http://bugs.sun.com/bugdatabase/view_bug.do;jsessionid=d76c6fabad9827be488fceb8d9f4?bug_id=4509080 Çok sayıda hata, düşük öncelikli. Eski bir okul java.net.Socket ile başlamak zorunda kalıyor gibi görünüyor. –

2

Bu, java.nio.channels.Channels'da bir hata gibi görünüyor (Tom Hawtin'e teşekkürler; bir dahaki sefere yanıt olarak gönderin). İyi bir açıklama ve çözüm, here (aslında Tom'un listelenen hanesinin bir kopyası) olarak açıklanmıştır:

Geçici çözüm testini yaptım ve işe yarıyor.

0

İlginç hata! Bununla birlikte, FileChannel # transferTo kullanamayacağınızı söylüyorsunuz. NIO olmayan soketin I/O akışlarını, Channelsl # newChannel'i kullanarak Kanallar'a aktarmadan önce, FileChannel # transferTo?

+0

"TransferTo", yalnızca WritableByteChannel'in, normal bir IO sınıfının bir sargısını değil, belirli bir desteğe sahip olduğu gerçek bir NIO sınıfıysa, performans avantajlarına sahip olduğunu düşünüyorum. Emin değil, tho. –

+0

Bunu düşünün, sanırım SocketChannel'i diğer cevaplardan birinde tarif edilen geçici bir ByteChannel ile sarmak, transferBunun faydalarını da ortadan kaldıracaktır. –

2

Hata raporundaki geçici çözüm benim için çalıştı. Çalışmanın geçici çözümü için yalnızca bir giriş veya çıkışının sarılması gerektiğini dikkate almalısınız - bu nedenle performans özellikle tek yönde önemliyse, daha az önemli olanı sarabilirsiniz ve diğerinin tüm optimizasyonları alacağından emin olun. mevcut.

public InputStream getInputStream() throws IOException { 
    return Channels.newInputStream(new ReadableByteChannel() { 
     public int read(ByteBuffer dst) throws IOException { 
      return socketChannel.read(dst); 
     } 
     public void close() throws IOException { 
      socketChannel.close(); 
     } 
     public boolean isOpen() { 
      return socketChannel.isOpen(); 
     } 
    }); 
} 

public OutputStream getOutputStream() throws IOException { 
    return Channels.newOutputStream(socketChannel); 
}