将大型数组传递给WCF服务

时间:2012-01-12 10:01:41

标签: c# wcf

我需要将一个大型数组传递给WCF服务。

当我试图这样做时,我收到了CommunicationException:

The socket connection was aborted. This could be caused by an error processing
your message or a receive timeout being exceeded by the remote host, or an 
underlying network resource issue. Local socket timeout was '24.00:59:59.9649980'.

我该如何解决?

代码:

服务器:

[ServiceContract(CallbackContract = typeof(ICallback))]
        public interface IService
        {
            [OperationContract]
            string Ping(string name);

            [OperationContract]
            int Count(string[] data);
        }

        public interface ICallback
        {
            [OperationContract]
            void OnPing(string pingText, DateTime time);
        }

        [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
        class ServiceImplementation : IService
        {
            #region IService Members

            public string Ping(string name)
            {
                Semaphore wait = new Semaphore(0,1);
                //get the callback item
                var callback = OperationContext.Current.GetCallbackChannel<ICallback>();
                if (callback!=null)
                {
                    new Thread(() =>
                    {
                        wait.WaitOne();
                        callback.OnPing(name, DateTime.Now);
                    }).Start();
                }                

                Console.WriteLine("SERVER - Processing Ping('{0}')", name);
                wait.Release();
                return "Hello, " + name;


            }

            #endregion



            public int Count(string[] data)
            {
                return data.Count();
            }
        }



        private static System.Threading.AutoResetEvent stopFlag = new System.Threading.AutoResetEvent(false);   

        public static void Main()
        {
            ServiceHost svh = new ServiceHost(typeof(ServiceImplementation));
            svh.AddServiceEndpoint(typeof(IService), new NetTcpBinding(),  "net.tcp://localhost:8000");

            // Check to see if the service host already has a ServiceMetadataBehavior
            ServiceMetadataBehavior smb = svh.Description.Behaviors.Find<ServiceMetadataBehavior>();
            // If not, add one
            if (smb == null)
                smb = new ServiceMetadataBehavior();
            //smb.HttpGetEnabled = true;
            smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
            svh.Description.Behaviors.Add(smb);

            // Add MEX endpoint
            svh.AddServiceEndpoint(
              ServiceMetadataBehavior.MexContractName,
              MetadataExchangeBindings.CreateMexTcpBinding(),
              "net.tcp://localhost:8000/mex"
            );

            svh.Open();   

            Console.WriteLine("SERVER - Running...");
            stopFlag.WaitOne();


            Console.WriteLine("SERVER - Shutting down...");
            svh.Close();   

            Console.WriteLine("SERVER - Shut down!");

        }



        public static void Stop()
        {
            stopFlag.Set();
        }


client:

        class Callback : IServiceCallback
        {
            static int s;
            int id = 0;
            public Callback()
            {
                id = s++;
            }
            public void OnPing(string pingText, DateTime time)
            {
                Console.WriteLine("\r\n{2}:Callback on \"{0}\"\t{1}",pingText,time,id);
            }
        }

        static Random rnd = new Random();

        static string GenetateStuff(int length)
        {
            StringBuilder sb = new StringBuilder();
            string s = "',.pyfgcrlaoeuidhtns;qjkxbmwvsz";
            for (int i = 0; i < length; i++)
            {
                sb.Append(s[rnd.Next(s.Length)]);
            }
            return sb.ToString();
        }

        static void Main(string[] args)
        {           

            InstanceContext ctx = new InstanceContext(new Callback());

             ServiceClient client = new ServiceClient(ctx);


             List<string> data = new List<string>();
            for (int i = 0; i < 10000; i++)
             {
                 data.Add(GenetateStuff(10000));
             }
            Console.WriteLine(client.Count(data.ToArray()));
        }

client xml:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
        <system.serviceModel>
            <bindings>
                <netTcpBinding>
                    <binding name="NetTcpBinding_IService" closeTimeout="24:01:00"
                        openTimeout="24:01:00" receiveTimeout="24:10:00" sendTimeout="24:01:00"
                        transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions"
                        hostNameComparisonMode="StrongWildcard" listenBacklog="10"
                        maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="10"
                        maxReceivedMessageSize="65536">
                        <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                            maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                        <reliableSession ordered="true" inactivityTimeout="00:10:00"
                            enabled="false" />
                        <security mode="Transport">
                            <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
                            <message clientCredentialType="Windows" />
                        </security>
                    </binding>
                </netTcpBinding>
            </bindings>
            <client>
                <endpoint address="net.tcp://localhost:8000/" binding="netTcpBinding"
                    bindingConfiguration="NetTcpBinding_IService" contract="TestTcpService.IService"
                    name="NetTcpBinding_IService">
                    <identity>
                        <userPrincipalName value="badasscomputing\menkaur" />
                    </identity>
                </endpoint>
            </client>
        </system.serviceModel>
    </configuration>

可以下载完整的项目here

1 个答案:

答案 0 :(得分:4)

替换以下行

    svh.AddServiceEndpoint(typeof(IService), new NetTcpBinding(),  "net.tcp://localhost:8000");

var tcpbinding = new NetTcpBinding();
            tcpbinding.MaxReceivedMessageSize = 2147483647;
            tcpbinding.ReaderQuotas.MaxArrayLength = 2147483647;
            tcpbinding.ReaderQuotas.MaxBytesPerRead = 2147483647;
            tcpbinding.ReaderQuotas.MaxStringContentLength = 2147483647;
            tcpbinding.ReaderQuotas.MaxDepth = 2147483647;
            svh.AddServiceEndpoint(typeof(IService), tcpbinding,  "net.tcp://localhost:8000");

注意:参考System.Runtime.Serialization.dll并导入命名空间

这应该增加所有大小的默认限制,应该没问题。同样找到通过代码添加maxObjInItemGraph的方法。