1

シンプルなプロキシサーバーを作成していますが、奇妙な状況に直面しました.コードに従っています:

var clientRequestStream = _tcpClient.GetStream();
var requestHeader = clientRequestStream.GetUtf8String();

GetUtf8StringStreamストリームを読み込むクラス(HttpRequestヘッダーを含む)の拡張メソッドです。Host と Requested Url にアクセスするには、これらのヘッダーを抽出する必要があります。NetworkStream の読み取りが完了したら。clientRequestStream.Position = 0;そのストリームを読み取って別のリモートに書き込む必要があるため、シーク操作を実行して設定する必要がありますNetworkStream

この問題をどのように解決すればよいかわかりません。アドバイスがあれば助かります。


編集: NetworkStream を MemoryStream にコピーしてから、MemoryStream でシーク操作を実行しようとしましたが、例外はありませんが、NetworkStream から読み取りたい場合、そのバッファーは常に空です。

また、リフレクターを使用して、内部で何が起こっているかを確認しましたStream.CopyTo。以下のコードを参照してください。

    private void InternalCopyTo(Stream destination, int bufferSize)
    {
        int num;
        byte[] buffer = new byte[bufferSize];
        while ((num = this.Read(buffer, 0, buffer.Length)) != 0)
        {
            destination.Write(buffer, 0, num);
        }
    }

これが CopyTo が行っていることです。使用してもCopyTo問題は解決しません。ソース(ここではNetworkStream)を最後まで読み込んでいるからです。この状況を処理する別の方法はありますか?

4

4 に答える 4

6

このストリームを最後まで読んでいますか?もしそうなら、コンテンツ全体を にコピーすることをお勧めします。そうすれば、それを心ゆくまでMemoryStream探すことができます。.NET 4 では、次のようにすると特に簡単Stream.CopyToです。

MemoryStream dataCopy = new MemoryStream();
using (var clientRequestStream = _tcpClient.GetStream())
{
    clientRequestStream.CopyTo(dataCopy);
}
dataCopy.Position = 0;
var requestHeader = dataCopy.GetUtf8String();

シーク可能でないことは理にかなってNetworkStreamいます。これは、サーバーが提供するデータのストリームにすぎません。サーバーに巻き戻しを指示できない限り(状況によっては意味があります)、巻き戻しに必要なだけのデータを何かがバッファリングしない限り、シークする方法はありMemoryStreamません。ファッション。

于 2012-07-31T21:12:40.203 に答える
3

あなたが発見したように、NetworkStreamシークできません。
NetworkStreamネットワークから直接データをフィードします。

データを に読み込んMemoryStreamで再利用する必要があります。

于 2012-07-31T21:11:57.867 に答える
1

シークを必要としないように GetUtf8String メソッドを適切に書き直したくないと仮定すると...

最も簡単な方法は、最初にストリームを MemoryStream にコピーすることです。ストリームがあれば、必要なだけシークできます。Stream.CopyToがコピーを処理します (.Net4+)

copiedStream.Position=0Position プロパティを 0 ( ) に設定するか、バッファと最初のメモリ ストリームの長さに基づいて新しいストリーム (できれば読み取り専用) を作成してストリームのクローンを作成し、結果の MemoryStream をシークする必要があることに注意してください。

于 2012-07-31T21:14:11.467 に答える
0

NetworkStream は転送専用であるため、clientRequestStream.Position = 0 を設定することはできません。ここを参照してください: http://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.position.aspx

NetworkStream を通常のストリームと同じように考えることに注意してください。たとえば StreamReader の Peek() のようなものは、アプリケーションをブロックする可能性があります。

于 2012-07-31T21:15:46.773 に答える