【问题标题】:Send Large Data with WCF without Streaming使用 WCF 发送大数据而不使用流式传输
【发布时间】:2013-07-11 18:44:57
【问题描述】:

我们正在尝试构建一个可以发送/接收 kb~gb 大小的大型数据文件的 Web 服务。

我知道我们应该使用流式传输来执行这样的操作,这样不会导致内存崩溃。

但问题是我们不想改变我们的设计,或者更像是,现在我们将尝试看看当我们使用 WCF 以字节 [] 缓冲传输模式传输大文件时会发生什么,比如仅 150mb 的文件. (我知道将整个文件缓冲到内存中......如果我们传输 gb 大小的文件,则会崩溃/异常......)

但即便如此,他们想看看会发生什么,所以我在 WCF 配置中有我的 wsHttpBinding:

  <system.web>
    <compilation debug="true"/>
      <httpRuntime maxRequestLength="524288"/>
  </system.web>
....

  <wsHttpBinding>
    <binding name="wsHttpBinding1" closeTimeout="00:10:00" openTimeout="00:10:00"
          receiveTimeout="00:30:00" sendTimeout="00:30:00" bypassProxyOnLocal="false"
          hostNameComparisonMode="StrongWildcard"                  
                                    maxBufferPoolSize="52428800" maxReceivedMessageSize="65536000"
          messageEncoding="Mtom" useDefaultWebProxy="true">
      <security mode="None" />
    </binding>
  </wsHttpBinding>

然后是我的客户端应用配置:

          <wsHttpBinding>
                <binding name="WSHttpBinding_IPrintService" closeTimeout="00:01:00"
                      openTimeout="00:01:00" receiveTimeout="00:30:00" sendTimeout="00:30:00"
                      bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                                    maxBufferPoolSize="52428800" maxReceivedMessageSize="65536000"
                      messageEncoding="Mtom" textEncoding="utf-8" useDefaultWebProxy="true"                           
                      allowCookies="false">
                      <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                            maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                      <reliableSession ordered="true" inactivityTimeout="00:10:00"
                            enabled="false" />
                  <security mode="None"/>
                </binding>
          </wsHttpBinding>

当我传输小数据时它工作正常,但是当我尝试传输 150mb 文件时,它给了我例外:

InnerException = {"无法将数据写入传输 连接:无法对套接字执行操作,因为 系统缺少足够的缓冲区空间或因为队列 已满。”}

我尝试增加 maxReceivedMessage 等,但还是有同样的问题....

======

编辑:我尝试将以上所有可能的值增加到... 2147483647 .... 我可以成功发送一个 30mb 的文件.. 但仍然不是 150mb.... 而且我也尝试使用这个 CustomBinding:

<customBinding>         
        <binding name="LargeCustomBinding" 
                 receiveTimeout="01:00:00"  
                 openTimeout="01:00:00"  
                 closeTimeout="01:00:00"  
                 sendTimeout="01:00:00"> 
          <binaryMessageEncoding  
            maxReadPoolSize="2147483647"  
            maxSessionSize="2147483647"  
            maxWritePoolSize="2147483647"> 
            <readerQuotas  
              maxArrayLength="2147483647"  
              maxDepth="2147483647"  
              maxBytesPerRead="2147483647"  
              maxNameTableCharCount="2147483647"  
              maxStringContentLength="2147483647" /> 
          </binaryMessageEncoding> 
          <httpTransport  
            maxBufferSize="2147483647"  
            maxReceivedMessageSize="2147483647"  
            maxBufferPoolSize="2147483647"/> 
        </binding> 
      </customBinding>

但我仍然遇到同样的问题......

=========

编辑 2:我想我应该关注我如何发送数据,也许我错了,我有一个 Object MyData:

    byte[] LargeData = File.ReadAllBytes(this.LargeDataPath.Text);
    MyData.LargeData = new List<KeyValuePair<string, byte[]>>()
    {
        new KeyValuePair<string, byte[]>("DATA", LargeData)
    };

    myServiceClient.SendDataAsync( new SendDataRequest(MyData));

应该没问题吧?我所做的只是在列表中发送一个大字节[].....

【问题讨论】:

  • 试试这个:maxStringContentLength="2147483646" maxArrayLength="2147483646"
  • 问题可能出在这里:maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"
  • 您是否通过 IIS 托管?它可能有一个最大值。强制执行内容大小。不记得在哪里检查这个...
  • @Dour High Arch:不,不是通过 IIS 托管。这发生在 Visual Studio 2010 中,我使用 WCF 服务库来创建服务。
  • 只是想知道:你解决了这里的问题吗?

标签: c# wcf


【解决方案1】:

您应该使用单独的发送方法调用发送较小的数据块。

将要发送的数据放入字节数组中。 然后实现两端的逻辑,这将知道如何处理大小并开始以更小的部分一个一个地发送数据。当您发送了整个文件后,它将被连接到客户端上的一个数组中,您将能够进行进一步的处理。

【讨论】:

  • 是的,我们确实提出了这种方法,但他们想先看看这样做会发生什么。
  • King,我不完全理解您的评论,尽管我 100% 确信您不应该尝试在一个服务包中发送大量数据。任何网络问题都会永久中断您的传输。使用“小块”方法,您可以重新发送部分数据,以防网络在短时间内保持沉默,因为连接是可恢复的。
  • 所以他们想让我做的只是实验,通过我肯定会发生这些问题。我可以预见您提到的问题,并且团队中的某个人已经编写了一个使用大块数据传输的示例代码。但是它们会导致设计发生变化(我们没有太多时间了)。所以经理现在只想尝试转移字节[]....即使我告诉他你告诉我的问题。
【解决方案2】:

先解决这个问题:

maxStringContentLength="8192"
maxArrayLength="16384"

并确保你有

maxStringContentLength="2147483646"
maxArrayLength="2147483646"

在客户端和服务器上。

我通过 WCF 发送 30Mb 没有问题。

然后查看this

【讨论】:

  • 奇怪...我尝试了您的修复并在您提供的链接中使用了 CustomBinding,但我仍然遇到相同的错误...我确实更新了 WCF 配置上的绑定,然后更新我的 cilent 配置....奇怪...
  • @king 确实很奇怪。异常指向maxBufferPoolSize="52428800",它只有 62Mbs。但如果你排除了这一点,我不知道出了什么问题。
  • @king 我建议通过发送越来越大的文件(以 1Mb 步长)来解决问题,以解决问题。一旦你完成了,你就会从配置中得到哪个常量把它搞砸了。
  • hmm 123mb 没问题,但直到 130mb 它死了...目前我正在尝试使用上面的 CustomBinding...
猜你喜欢
  • 1970-01-01
  • 2011-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-23
  • 1970-01-01
  • 1970-01-01
  • 2011-02-15
相关资源
最近更新 更多