4

テスト目的のためだけに WCF ストリーミングの例を作成しようとしましたが、実際にストリーミングされているかどうかはわかりません。

サンプルは非常に基本的なものです。

  1. サーバーは大きなバイナリ コンテンツを返します (この場合は PDF ファイル)
  2. クライアントが大きなバイナリ コンテンツをファイルに書き込みます。

ただし、ストリーミング転送用にサーバーとクライアントの両方を正しく構成したと信じているにもかかわらず、問題があるようです。

  1. IOExceptionメッセージに遭遇しているため、実際にはストリーミング転送ではないようですThe maximum message size quota for incoming messages (65536) has been exceeded
  2. ストリーム バッファを 8192 (またはその他のサイズ) に設定した場合でも、読み取りは 1536 バイト単位で行われます。

完全なホスト コードは次のとおりです。

using System;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Description;

namespace WcfStreamingHost
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            BasicHttpBinding binding = new BasicHttpBinding();
            binding.TransferMode = TransferMode.Streamed;
            binding.MaxBufferSize = 65536;
            binding.MaxReceivedMessageSize = 65536;
            binding.ReaderQuotas.MaxBytesPerRead = 65536;
            binding.SendTimeout = TimeSpan.FromMinutes(10);

            ServiceHost host = new ServiceHost(typeof (ContentProvider), new Uri("http://charles-m4600:1234/contentprovider"));

            host.Description.Behaviors.Add(new ServiceMetadataBehavior());
            host.Description.Behaviors.Find<ServiceDebugBehavior>().IncludeExceptionDetailInFaults = true;
            host.AddServiceEndpoint(typeof (IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
            host.AddServiceEndpoint(typeof (IContentProvider), binding, "streamed");

            host.Open();

            Console.ReadKey();
        }
    }

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Single)]
    public class ContentProvider : IContentProvider
    {
        #region IContentProvider Members

        [OperationBehavior(AutoDisposeParameters = true)]
        public Stream GetFile()
        {
            Stream stream = File.OpenRead("large_file.pdf");

            return stream;
        }

        #endregion
    }

    [ServiceContract]
    public interface IContentProvider
    {
        [OperationContract]
        Stream GetFile();
    }
}

完全なクライアント コードは次のとおりです。

using System;
using System.IO;
using System.ServiceModel;
using WcfStreamingClient.LocalSvc;

namespace WcfStreamingClient
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            BasicHttpBinding binding = new BasicHttpBinding();
            binding.TransferMode = TransferMode.Streamed;
            binding.MaxBufferSize = 65536;
            binding.MaxReceivedMessageSize = 65536;
            binding.ReaderQuotas.MaxBytesPerRead = 65536;
            binding.ReceiveTimeout = TimeSpan.FromMinutes(10);

            EndpointAddress address = new EndpointAddress("http://charles-m4600:1234/contentprovider/streamed");

            using (ContentProviderClient client = new ContentProviderClient(binding, address))
            {
                using (Stream stream = client.GetFile())
                {
                    FileInfo file = new FileInfo("output.pdf");

                    if (file.Exists)
                    {
                        file.Delete();
                    }

                    using (FileStream fileStream = file.Create())
                    {
                        const int bufferLen = 8192;
                        byte[] buffer = new byte[bufferLen];
                        int count = 0;
                        int total = 0;
                        while ((count = stream.Read(buffer, 0, bufferLen)) > 0)
                        {
                            fileStream.Write(buffer, 0, count);
                            total += count;
                            Console.Out.WriteLine("Read {0} bytes", total);
                        }
                    }
                }
            }
        }
    }
}

この問題に関する他のさまざまな投稿を読みましたが、手がかりが見つからないようです。

4

2 に答える 2

4

あなたの投稿はかなり前のものでしたが、私はそれを偶然見つけて、私の発見を共有したいと思いました.

最大メッセージ サイズ クォータは常に考慮されます。ストリーミング転送があるかどうかは関係ありません。MSDNはそれについて非常に明確です。最大バッファサイズを追加で指定できます。

http://msdn.microsoft.com/en-us/library/ms731078%28v=vs.100%29.aspx

MaxReceivedMessageSize : トランスポートが例外を発生させる前に、受信したメッセージ (ヘッダーを含む) の最大サイズ (バイト単位)。

MaxBufferSize : データのストリーミングに使用されるバッファーの最大サイズ (バイト単位)。このトランスポート クォータが設定されていない場合、またはトランスポートがストリーミングを使用していない場合、クォータ値は MaxReceivedMessageSize クォータ値と MaxValue の小さい方と同じになります。

なぜ常に1536 バイトのチャンクを持っているのか、私にはよくわかりません。しかし、イーサネット フレーム(ジャンボ フレームを除く)の最大サイズが原因だと思います。

http://en.wikipedia.org/wiki/Ethernet_frame

于 2014-02-05T16:38:36.933 に答える
2

MaxReceivedMessageSize は、着信チャネルに対する DOS 攻撃を防ぐためにあり、MaxBufferSize はチャネルのメッセージ バッファサイズを制御します。チャネルがストリーミング用に構成されている場合、soap ヘッダーのみがバッファリングされ、本文がストリーミングされます。ストリーム チャンク サイズは、サービスの実装 (この場合は 8Kb) によって制御されます。 maxrecievedmessagesize は、ファイル + ヘッダーのサイズを制限します。maxrecieved メッセージ サイズは、バッファリング モードのファイル MaxBufferSize のサイズと等しくなければなりません。ただし、ストリーミングでは MaxBufferSize を小さくする必要があり、MaxRecievedMessafeSize は予想されるファイル サイズです。ストリーミング モードでは、MaxBufferSize を使用して DOS 攻撃を防ぐことができます。

于 2012-06-30T06:54:52.917 に答える