2016-06-24 31 views
0

當我在本地運行下面(在我自己的計算機上)時,它工作正常 - 我可以向它發送消息並正確讀取它們。只要我把它放在遠程服務器上併發送消息,只有一半的消息被讀取。AsynchronousSocketChannel無法在整個消息中讀取

try { 
      this.asynchronousServerSocketChannel = AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(80)); 
      this.asynchronousServerSocketChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() { 
       @Override 
       public void completed(AsynchronousSocketChannel asynchronousSocketChannel, Void att) { 
        try { 
         asynchronousServerSocketChannel.accept(null, this); 
         ByteBuffer byteBuffer = ByteBuffer.allocate(10485760); 
         asynchronousSocketChannel.read(byteBuffer).get(120000, TimeUnit.SECONDS); 
         byteBuffer.flip(); 
         System.out.println("request: " + Charset.defaultCharset().decode(byteBuffer).toString()); 

        } catch (CorruptHeadersException | CorruptProtocolException | MalformedURLException ex) { 

        } catch (InterruptedException | ExecutionException | TimeoutException ex) { 

        } 
       } 

       @Override 
       public void failed(Throwable exc, Void att) { 
       } 
      }); 
     } catch (IOException ex) { 
     } 

我環顧了其他questions並嘗試了一些答案,但目前爲止沒有任何工作。我認爲原因可能是因爲它遠程放置時網絡速度較慢,但​​增加超時並不能解決問題。我也認爲該消息可能太大,但爲ByteBuffer分配更多容量也不能解決問題。

+0

沒有這樣的事作爲TCP中的消息。這是一個字節流協議。如果你想要消息,你必須自己實現它們。 – EJP

+0

對不起,我正在使用一個瀏覽器,我相信這個瀏覽器是通過一個'byte []'發送的,對我而言這個詞的選擇不正確 – Hooli

+0

同樣的區別。 'Message'=='byte array'在這種情況下。這是一個字節流協議。沒有什麼說可以在單個操作中接收整個發送的字節數組。 – EJP

回答

0

我相信你的問題與你正在使用的代碼的異步性質。你擁有的是一個開放的連接,你在套接字上調用了異步的read方法。 這會從通道中讀取n字節,其中n0之間的任何值,與可用緩衝區的大小相同。

我堅信你必須循環閱讀。也就是說,用Java的A-NIO;你需要通過再次從completed方法調用readCompletionHandler,可能在AsynchronousSocketChannel通過作爲附件到一個新的completed方法上CompletionHandler您創建read,而不是一個你已經有accept方法。

我認爲這是同一種模式,你會使用,你會再次thisCompletionHandler你使用的accept方法調用調用accept爲完成處理從completed方法。

它便成爲重要的是把一個「逃生」條款到您的CompletionHandler例如,如果result-1或者如果ByteBuffer讀過X根據你期待什麼,或者如果最終基於字節數byteByteBuffer是您已經與發送應用程序達成一致的特定消息終止字節。

對此事的Java Documentation去,至於說read方法只會在調用時讀取的字節對dst量。

總結; completed方法調用read的處理程序似乎在一些事情被寫入通道後執行;但是如果有東西正在流傳,你可能會得到一半的字節,所以你需要繼續閱讀,直到你滿意爲止,你已經完成了他們發送的內容。

下面是一些代碼,我一直在閱讀,直到最後,在異步閱讀時作出響應。它不像我自己,可以同時談話和傾聽。

public class ReadForeverCompletionHandler implements CompletionHandler<Integer, Pair<AsynchronousSocketChannel, ByteBuffer>> { 
@Override 
public void completed(Integer bytesRead, Pair<AsynchronousSocketChannel, ByteBuffer> statefulStuff) { 
    if(bytesRead != -1) { 
     final ByteBuffer receivedByteBuffer = statefulStuff.getRight(); 
     final AsynchronousSocketChannel theSocketChannel = statefulStuff.getLeft(); 
     if (receivedByteBuffer.position()>8) { 
      //New buffer as existing buffer is in use 
      ByteBuffer response = ByteBuffer.wrap(receivedByteBuffer.array()); 
      receivedByteBuffer.clear(); //safe as we've not got any outstanding or in progress reads, yet. 
      theSocketChannel.read(receivedByteBuffer,statefulStuff,this); //Basically "WAIT" on more data 
      Future<Integer> ignoredBytesWrittenResult = theSocketChannel.write(response); 
     } 
    } 
    else { 
     //connection was closed code 
     try { 
      statefulStuff.getLeft().shutdownOutput(); //maybe 
     } 
     catch (IOException somethingBad){ 
      //fire 
     } 
    } 
} 

@Override 
public void failed(Throwable exc, Pair<AsynchronousSocketChannel, ByteBuffer> attachment) { 
    //shout fire 
} 

的讀取時最初從completed方法拉開序幕由呼叫處理程序從最原始的異步accept服務器套接字像

public class AcceptForeverCompletionHandler implements CompletionHandler<AsynchronousSocketChannel, Pair<AsynchronousServerSocketChannel, Collection<AsynchronousSocketChannel>>> { 

private final ReadForeverCompletionHandler readForeverAndEverAndSoOn = new ReadForeverCompletionHandler(); 

@Override 
public void completed(AsynchronousSocketChannel result, Pair<AsynchronousServerSocketChannel, Collection<AsynchronousSocketChannel>> statefulStuff) { 
    statefulStuff.getLeft().accept(statefulStuff, this); //Accept more new connections please as we go 
    statefulStuff.getRight().add(result); //Collect these in case we want to for some reason, I don't know 
    ByteBuffer buffer = ByteBuffer.allocate(4098); //4k seems a nice number 
    result.read(buffer, Pair.of(result, buffer),readForeverAndEverAndSoOn); //Kick off the read "forever" 
} 

@Override 
public void failed(Throwable exc, Pair<AsynchronousServerSocketChannel, Collection<AsynchronousSocketChannel>> attachment) { 
    //Shout fire 
} 

}

相關問題