WCF在自托管服务上流式传输大数据(500MB / 1GB)

我目前遇到一个问题,试图使用WCF自托管服务(没有IIS)发送大数据。 使用流式传输结果传输500MB,我的服务因System.OutOfMemoryException而崩溃。 是否有可能传输这么多数据?

这是我的WCF配置:

                                    

我的客户端配置:

                     

你不需要设置如此高的maxBufferSizemaxBufferPoolSize这些可能导致你的内存不足exception。 默认值应该没问题。

查看MSDN上的大数据和流 , 特别是大数据的特殊安全注意事项这一部分文章很重要

需要MaxBufferSize属性来约束WCF缓冲的内存。 在流式传输时将其设置为安全值(或将其保持为默认值)非常重要。 例如,假设您的服务必须接收最大4 GB的文件并将它们存储在本地磁盘上。 还假设您的内存受限制,一次只能缓冲64 KB的数据。 然后,您将MaxReceivedMessageSize设置为4 GB,MaxBufferSize设置为64 KB。 此外,在服务实现中,必须确保只读取64 KB块中的传入流,并且在将上一个块写入磁盘并从内存中丢弃之前不要读取下一个块。

我整理了一个非常简单的示例,将数据从自托管服务流式传输到控制台客户端。 为了保持post简短,我只添加了服务器代码和部分客户端。

服务合同

 using System.IO; using System.ServiceModel; namespace Service { [ServiceContract] public interface IStream { [OperationContract] Stream GetLargeObject(); } } 

服务实现

 using System; using System.IO; using System.ServiceModel; namespace Service { [ServiceBehavior] public class StreamService : IStream { public Stream GetLargeObject() { // Add path to a big file, this one is 2.5 gb string filePath = Path.Combine(Environment.CurrentDirectory, "C:\\Temp\\BFBC2_PC_Client_R11_795745_Patch.exe"); try { FileStream imageFile = File.OpenRead(filePath); return imageFile; } catch (IOException ex) { Console.WriteLine(String.Format("An exception was thrown while trying to open file {0}", filePath)); Console.WriteLine("Exception is: "); Console.WriteLine(ex.ToString()); throw; } } } } 

服务主要

 using System; using System.ServiceModel; namespace Service { class Program { static void Main(string[] args) { try { using (var serviceHost = new ServiceHost(typeof(StreamService))) { serviceHost.Open(); Console.WriteLine("Press Any Key to end"); Console.ReadKey(); } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } } } } 

服务app.config

                                

启动服务,可能需要在管理员帐户下运行才能打开套接字。 创建客户端控制台应用程序并使用URL http:// localhost:8080 / StreamService添加服务引用,使用Service作为生成的客户端的命名空间。

客户主要

 using System; using System.IO; using Client.Service; namespace Client { class Program { static void Main(string[] args) { try { using (StreamClient streamClient = new StreamClient()) { streamClient.Open(); using (FileStream fileStream = new FileStream("c:\\temp\\bigfile.exe",FileMode.Create)) { streamClient.GetLargeObject().CopyTo(fileStream); } } Console.WriteLine("Press any key to end"); Console.ReadKey(); } catch (Exception ex) { Console.WriteLine(ex); } } } } 

生成的客户端配置文件需要稍微修改,增加receiveTimeout并设置maxReceivedMessageSize =“4294967295”

                   

启动服务然后启动客户端。 它会流畅地传输一个大文件。