WCF流传输 - 限制速度

7

我在我的应用程序中遇到了一个严重的问题,已经几个月了,但没有找到好的解决方法。我注意到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,它都不会每次都开始,而是每隔 X 次调用一次 FileStreamWatching.Read。很奇怪。

*稍后查看输出

    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时客户端的输出:

数组长度:256,读取:256


数组长度:4096,读取:4096


数组长度:65536,读取:65536


数组长度:65536,读取:65536


数组长度:65536,读取:65536


数组长度:65536,读取:65536


……直到文件传输完成。

问题:

  1. 我传递给read方法的缓冲区长度不是256/4096/65536,而是1000。
  2. 从服务调用它时,FileStreamWatching类中的Read并不会每次都开始。

我的目标:

  1. 控制每次接收客户端数据的大小。

  2. 每次从服务调用FileStreamWatching.Read时它都能开始。

我的客户端配置:

<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();

MyStream.Read(buffer, 0, buffer.Length) - 每次调用后偏移量不应该增加吗? - Tisho
@Tisho 应用程序可能在每次调用时更改偏移量。无论它是否更改,都不会影响 Stav 在代码的这一点上的问题。 - Jesse Chisholm
1个回答

2

关于为什么使用256/4K/65535:

我看到这里有两种可能性:

  • 基本的FileStream正在进行自己的内部缓冲。 它可能在内部调用read(array,offset,length)以填充它的内部缓冲区,然后返回你请求的部分。 内部调用最终会变成递归调用,直到它读取完整个文件。 然后您的重写将停止显示任何内容。
  • 您没有展示被覆盖的其他stream.read()签名。如果任何代码路径最终调用了其他read方法之一,则您的计数就会出错。

关于MyStream每次不重新开始:

MyStream参数是否被处理过?还是被重复使用于一个新流?您的代码只在构造函数中“重新启动”,因此在更改传入的流时,请确保对象已被处理并重新构建。

当到达EOF时,您可以测试递归EOF情况,也可以显示一些内容。

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

-Jesse


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接