2016-10-06 3 views
0

これはではありません。要求されたものより少ないストリームを処理する方法に関する質問。私はそれをどのように処理したかを示し、コメントは大歓迎です。StreamSocketに基づくストリームは、要求されたデータよりも少ないデータを返します

しかし、最初の最初のもの:

私はTCP通信のためのStreamSocketをベースUWPを使用しています。

StreamSocket strs = GetConnection(); 
Stream str = strs.InputStream.AsStreamForRead(); 

私たちは、送信を想定しています。最初の数バイトは、他のものの中で、伝送がどれくらい長くなるかを教えてくれます。次に、指定されたバッファサイズで指定された量のデータを読み込むメソッドにストリームを渡します。私はまったくの警告を取得していない小さな伝送のための

最初の実装

// commencing data read: 
int ret = 0; 
int total = 0; 
for(int k = 0; k < size; k += buffserSize) { 
    int len = Math.Min(bufferSize, size - k); 
    ret = stream.Read(data, k, len); 
    if(ret != len) 
      Debug.WriteLine("Congestion: {0}/{1}", ret, len); // throw? 
    total += ret; 
} 

。しかし、より大きなトランスミッションの場合、トランスミッションが約40kBになると、私は一貫して、要求されるよりも少ないデータしか得られません。この実装ではデータが失われます。

ソリューション

だから私はに持ってネットワークストリームで読んブロッキングはいくつかの点で要求されたよりも少ないを返すことを考慮に入れます。だから私は、このソリューションを実装約40KB私は混雑を取得した後、再び

int bs = 4096; 
int rpos = 0; 
while(rpos < size) { 
    int len = Math.Min(bs, size - rpos); 
    int read = stream.Read(data, rpos, len); 
    if(read < bs) { 
     Debug.WriteLine("Congestion: {0}/{1}.", read, len); 
     bs /= 2; 
    } 
    rpos += read; 
} 

を、私はそれ(とボーナスとしてバッファサイズ=悪い-マン・フロー制御を減らす)

を占め、この時間これは

は、なぜ私は読んブロックに要求されたよりも少ないデータを返すためにTCPソケットに基づいてストリームを期待する必要があります実際の

質問に私をもたらします。

TCPは独自のフロー制御を既に持っているという印象を受けました。トラフィック(バイト/秒)が増加してから(突然)低下する理由を説明します。

しかし、ではなく、は、十分なデータが到着するまで、読み取りが待機しない理由を説明します。私はこれを下の1つの抽象レイヤーとして扱うべきだと考えました。

+0

をチェックする必要があり、「私は、これは以下の1つの抽象化層を処理する必要がありますと思いました。」どうして? TCPが提供する抽象化は、(潜在的に無限の)双方向のバイトストリームです。 * messages *が必要な場合は、自分で実装するか(ここでやっているように)、より高いレベルの抽象化に移行するかはあなた次第です。 –

+0

私はストリームが提供する抽象概念を意味すると思います。しかし、私は誤解があるようです。私がnバイトを要求すると、ストリームが私にnバイトを与えると期待しています。特定の(まれな)状況においてのみ、ストリームが少なくなると期待します。 – MrPaulch

+0

[文書化されています](https://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.read(v = vs.110).aspx): " *利用可能なデータ量*、 'size'パラメータで指定されたバイト数まで(私の強調) –

答えて

2

これは、下の1つの抽象レイヤーで処理する必要があると考えました。

なぜですか? TCPが提供する抽象化は、(潜在的に無限の)双方向のバイトストリームです。メッセージが必要な場合は、自分で実装するか(より上のレベルの抽象化に移るか)を決定することができます。

は、ストリームが提供する抽象概念です。しかし、私は誤解があるようです。私がnバイトを要求すると、ストリームが私にnバイトを与えると期待しているので、

残念ながら、それは誤解です。

バッファに読み込まれたバイトの総数:一部Stream実装は、そのような保証を提供することができる場合があり、一方、抽象StreamクラスがReadメソッドを定義します。これは

、その多くのバイトが現在利用できない場合、要求されたバイト数よりも少なくすることができ、そうNetworkStreamは、このような柔軟性を活用する - それはあなたに、少なくとも1バイトと一度、それは便利できる限りを与えます利用可能なデータがいくつかあります。

あなたのユースケースに合っていませんが、一部のコンシューマは利用可能なデータであればどんなものでも動作する可能性があるため、大きなバッファを提供する可能性があります(データが大量にある場合など)は単なる1バイトで便利です。それらの消費者はあなたと同じAPIを正確に呼び出すことになり、その動作はニーズに合っています。

0

BinaryReaderクラスは、私が誤解していた抽象レイヤーを提供するReadBytes(int count)というメソッドを提供しています。

すなわち、それがあれば、それがストリームの終わりに達していないようにバイトの要求された量を返します。

戻り値 型:System.Byte []

バイト配列を含有します基礎となるストリームから読み取られたデータこれは、ストリームの終わりに達した場合に要求されたバイト数よりも小さい可能性があります。

そんなに多くの単純な解決策があります:

var bReader = new BinaryReader(stream); 
byte[] data = bReader.ReadBytes(size); 

は、一つはまだIOException

関連する問題