3

TCP 接続を使用してサーバーに接続し、バイナリ ドキュメントを読み取り、それを応答オブジェクトに書き込む Web アプリがあります。つまり、カスタム プロトコルを使用してバックエンド サーバーからファイルを転送し、そのファイルを HTTP 経由でクライアントに返します。

サーバーはステータス コードと MIME タイプを送信します。これを正常に読み取り、ファイルの内容を書き込み、ソケットを閉じます。これはうまくいくようです。

クライアント (C# Web アプリ) は、データを読み取ります。

     private NetworkStream stream_;

     public void WriteDocument(HttpResponse response)
     {
        while (stream_.DataAvailable)
        {
           const int bufsize = 4 * 1024;
           byte[] buffer = new byte[bufsize];
           int nbytes = stream_.Read(buffer, 0, bufsize);
           if (nbytes > 0)
           {
              if (nbytes < bufsize)
                 Array.Resize<byte>(ref buffer, nbytes);
              response.BinaryWrite(buffer);
           }
        }
        response.End();
     }

これは、すべてのデータが到着する前に常に読み取りループを終了するようです。私は何を間違っていますか?

4

4 に答える 4

3

OutputStream汎用関数で直接使用します。を使用するStreamと、 を制御できますFlush

    public void WriteDocument(HttpResponse response) {
        StreamCopy(response.OutputStream, stream_);
        response.End();
    }

    public static void StreamCopy(Stream dest, Stream src) {
        byte[] buffer = new byte[4 * 1024];
        int n = 1;
        while (n > 0) {
            n = src.Read(buffer, 0, buffer.Length);
            dest.Write(buffer, 0, n);
        }
        dest.Flush();
    }
于 2008-09-21T15:24:12.290 に答える
2

これが私がすることです。通常、データ格納ループをいつ終了するかを知るには、コンテンツの長さが必要です。プロトコルがヘッダーとして期待する量のデータを送信しない場合は、送信の終了を知らせるために何らかのマーカーを送信する必要があります。

DataAvailable プロパティは、ソケットから読み取るデータがあるかどうかを通知するだけで、送信するデータがさらにあるかどうかはわかりません (また、わかりません)。ソケットがまだ開いていることを確認するには、stream_.Socket.Connected && stream_.Socket.Readable をテストします。

    public static byte[] doFetchBinaryUrl(string url)
    {
        BinaryReader rdr;
        HttpWebResponse res;
        try
        {
            res = fetch(url);
            rdr = new BinaryReader(res.GetResponseStream());
        }
        catch (NullReferenceException nre)
        {
            return new byte[] { };
        }
        int len = int.Parse(res.GetResponseHeader("Content-Length"));
        byte[] rv = new byte[len];
        for (int i = 0; i < len - 1; i++)
        {
            rv[i] = rdr.ReadByte();
        }
        res.Close();
        return rv;
    }
于 2008-09-21T15:20:07.963 に答える
1

.Net でどのように機能するかはわかりませんが、私が作業したほとんどの環境では、接続が閉じられると Read() は 0 バイトを返します。したがって、次のようにします。

文字バッファ[4096];
int num_read;

while ( num_read = src.Read(sizeof(buffer)) > 0 )
{
   dst.Write(バッファ、num_read);
}
于 2008-09-21T16:15:18.190 に答える
1

問題の根本は次の行です。

while (stream_.DataAvailable)

DataAvailable は、ストリーム バッファー内に読み取りと処理の準備ができているデータがあることを意味します。ストリームの「終わり」に到達したことを保証するものではありません。特に、送信に一時停止がある場合、または送信者がリーダーよりも遅い場合、DataAvailable は false になる可能性があります。

于 2008-10-30T11:21:31.197 に答える