3

我有一个 Web 应用程序,它使用 TCP 连接连接到服务器并读取二进制文档,然后将其写入其响应对象。换句话说,它使用自定义协议从后端服务器传输文件,并通过 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];
整数读;

而 ( num_read = src.Read(sizeof(buffer)) > 0 )
{
   dst.Write(buffer, num_read);
}
于 2008-09-21T16:15:18.190 回答
1

你的问题的根源是这一行:

while (stream_.DataAvailable)

DataAvailable 仅表示流缓冲区中有数据可供读取和处理。它不能保证已经到达流的“结束”。特别是,如果传输中有任何暂停,或者如果您的发件人比您的阅读器慢,则 DataAvailable 可能是错误的。

于 2008-10-30T11:21:31.197 回答