简体   繁体   中英

Passing a large array to a WCF service

I need to pass a large array into a WCF service.

When I'm trying to do that, I'm getting 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'.

How do I fix that?

The code:

server:

[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>

the full projects can be downloaded here .

Replace the following line

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

with

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

NOTE: Reference System.Runtime.Serialization.dll and import the namespace

That should increase all the default limits on the size and should be fine. Similarly find the way to add the maxObjInItemGraph via code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM