2008-09-21 17 views
3

我有一个网络应用程序,它使用TCP连接连接到服务器,并读取二进制文件,然后写入其响应对象。换句话说,它使用自定义协议从后端服务器传输文件,并通过HTTP将该文件返回给其客户端。如何确定NetworkStream中没有更多数据需要读取?

服务器发送一个状态码和一个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(); 
    } 

这似乎永远退出读循环中的所有数据已经​​到达之前。我究竟做错了什么?

回答

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(); 
    } 
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; 
    } 
+0

我真的不能这样做。返回的数据是二进制的,所以我不能真正使用任何种类的标记。它也是随时产生的,可能会相当大,所以我不想在知道尺寸之前缓冲它。 – Ferruccio 2008-09-21 15:32:42

+0

我希望DataAvailable表示服务器没有关闭套接字。 – Ferruccio 2008-09-21 15:33:43

1

不知道事情怎么净工作,但在大多数环境中我在read()返回0字节工作时,连接被关闭。所以,你会做这样的事情:

 
char buffer[4096]; 
int num_read; 

while (num_read = src.Read(sizeof(buffer)) > 0) 
{ 
    dst.Write(buffer, num_read); 
} 
1

你的问题的根源在于这一行:

while (stream_.DataAvailable) 

DataAvailable只是意味着要读取和处理存储在流缓存准备有数据。它不能保证已经到达的流的“结束”。特别是,如果传输中存在任何暂停,或者您的发件人比读者慢,DataAvailable可能为false。

相关问题