WCF流 - 限制速度

时间:2012-05-26 19:53:48

标签: c# wcf wcf-streaming

在我的申请中,这是一个严重的问题,几个月没有找到任何好的解决方案。 我注意到C#管理了Stream类在WCF中流式传输的方式,而没有考虑我的配置。

首先,我有一个继承自FileStream的类,因此我可以随时观察从客户端读取的内容:

public class FileStreamWatching : FileStream
    {
        /// <summary>        
        /// how much was read until now        
        /// </summary>        
        public long _ReadUntilNow { get; private set; }
        public FileStreamWatching(string Path, FileMode FileMode, FileAccess FileAccess)
            : base(Path, FileMode, FileAccess)
        {
            this._ReadUntilNow = 0;
        }
        public override int Read(byte[] array, int offset, int count)
        {
            int ReturnV = base.Read(array, offset, count);
            //int ReturnV = base.Read(array, offset, count);
            if (ReturnV > 0)
            {
                _ReadUntilNow += ReturnV;
                Console.WriteLine("Arr Lenght: " + array.Length);
                Console.WriteLine("Read: " + ReturnV);
                Console.WriteLine("****************************");
            }
            return ReturnV;
        }
    }

其次,下面是我读取包含该文件的客户端流的服务方法。 我的主要问题是FileStreamWatching.Read每次从下面这个方法召唤它时都没有启动,而是FileStreamWatching.Read每次X次启动一次我调用它。奇怪。

* 稍后查看输出

    public void Get_File_From_Client(Stream MyStream)
    {
        using (FileStream fs = new FileStream(@"C:\Upload\" + "Chat.rar", FileMode.Create))
        {
            byte[] buffer = new byte[1000];
            int bytes = 0;
            while ((bytes = MyStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                fs.Write(buffer, 0, bytes);
                fs.Flush();
            }
        }
    }

这是每次激活FileStreamWatching.Read时客户端的输出:(重新启动缓冲区长度仅为1000!)

Arr Lenght:256, 阅读:256


Arr Lenght:4096, 阅读:4096


Arr Lenght:65536, 阅读:65536


Arr Lenght:65536, 阅读:65536


Arr Lenght:65536, 阅读:65536


Arr Lenght:65536, 阅读:65536


....直到文件传输完成。

问题:

  1. 我带到读取方法的缓冲区的长度不是256/4096/65536。它是1000。
  2. 每次从服务中调用时,FileStreamWatching类中的Read都不会启动。
  3. 我的目标:

    1. 控制每次读取从客户端重新开始的次数。

    2. 每次从服务中调用FileStreamWatching.Read都会启动。

    3. 我的客户端配置:

      <configuration>
          <system.serviceModel>
              <bindings>
                  <basicHttpBinding>
                      <binding name="BasicHttpBinding_IJob" transferMode="Streamed"/>
                  </basicHttpBinding>
              </bindings>
              <client>
                  <endpoint address="http://localhost:8080/Request2" binding="basicHttpBinding"
                      bindingConfiguration="BasicHttpBinding_IJob" contract="ServiceReference1.IJob"
                      name="BasicHttpBinding_IJob" />
              </client>
          </system.serviceModel>
      </configuration>
      

      我的服务配置(此处没有配置文件):

              BasicHttpBinding BasicHttpBinding1 = new BasicHttpBinding();
              BasicHttpBinding1.TransferMode = TransferMode.Streamed;
              //
              BasicHttpBinding1.MaxReceivedMessageSize = int.MaxValue;
              BasicHttpBinding1.ReaderQuotas.MaxArrayLength = 1000;
              BasicHttpBinding1.ReaderQuotas.MaxBytesPerRead = 1000;
              BasicHttpBinding1.MaxBufferSize = 1000;
              //
              ServiceHost host = new ServiceHost(typeof(JobImplement), new Uri("http://localhost:8080"));
              //
              ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
              behavior.HttpGetEnabled = true;
              //
              host.Description.Behaviors.Add(behavior);
              ServiceThrottlingBehavior throttle = new ServiceThrottlingBehavior();
              throttle.MaxConcurrentCalls = 1;
              host.Description.Behaviors.Add(throttle);
              //
              //
              host.AddServiceEndpoint(typeof(IJob), BasicHttpBinding1, "Request2");
              host.Open();
      

1 个答案:

答案 0 :(得分:2)

re:为什么256 / 4K / 65535?

我发现有两种可能性:

  • 基地FileStream正在进行自己的内部缓冲。它可能在内部调用read(array,offset,length)来填充其内部缓冲区,然后传回您要求的部分。内部调用最终是递归的,直到它读取整个文件。然后你的覆盖停止显示任何内容。
  • 您还没有显示其他stream.read()个签名被覆盖。如果任何代码路径最终调用其他read方法之一,那么您的计数将会关闭。

re:MyStream不是每次都重新开始

MyStream参数是否已被处理?或者它是否被重新用于新流?您的代码仅在构造函数中“重新启动”,因此当您更改传入流时,确定对象将被处置并重新构建。

您可以通过在达到EOF时显示内容来测试递归EOF案例。

如果添加计算MyStream.Read的应用程序调用和方法入口/出口的静态变量,则可以测试意外的递归。如果它们不匹配,则FileStream正在进行内部(意外递归)调用。

-Jesse