• WCF全双工数据传输


    项目结构:


    客户端:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    using System.Runtime.Serialization.Formatters.Binary;
    using System.IO;
    using System.Runtime.Serialization;
    using System.Collections;
    
    
    using Cn100.Wcf.Duplex.Contract;
    using Cn100.Wcf.Duplex.Service;
    using Cn100.Wcf.Duplex.Common;
    using System.ServiceModel.Description;
    
    
    namespace Cn100.Wcf.Duplex.Client
    {
       public delegate void DuplexCallBack(object reust,int count);
    
        public class ClientHandler : ICallback,IDisposable
        {
            /// <summary>
            /// 处理回调事件的类
            /// </summary>
            public static event DuplexCallBack callback;
    
            public Hashtable hashResult = new Hashtable();
            public StringBuilder builder = new StringBuilder();
    
            private static DuplexChannelFactory<ICallbackService> channelFactory = null;
    
            /// <summary>
            /// 接收回传数据
            /// </summary>
            /// <param name="result"></param>
            /// <param name="count"></param>
            /// <param name="isComplete"></param>
            public void ReceiveData(object result, int count, int index, bool isComplete)
            {
                if (isComplete)
                {
                    //ArrayList array = new ArrayList(hashResult.Keys);
                    //array.Sort();
                    //StringBuilder builder = new StringBuilder();
                    //foreach (int key in array)
                    //{
                    //    builder.Append(hashResult[key].ToString());
                    //}
                    object obj = new object();
                    if (builder.Length > 0)
                    {
                         obj = SerializeHelper.DeserializeObject(builder.ToString());
                        builder = new StringBuilder();
                    }
                    else
                    {
                        obj = result;
                    }
    
                    if (callback != null)
                    {
                        callback(obj, count);
                        //callback = null;
                    }
    
                    
                    HideProcess();
                }
                else
                {
                    builder.Append(result.ToString());
                    //hashResult.Add(index, result);
                }
            }
    
            /// <summary>
            /// 显示进度条
            /// </summary>
            public void ShowProcess()
            { 
            
            }
    
            /// <summary>
            /// 隐藏进度条
            /// </summary>
            public void HideProcess()
            { 
            
            }
    
            public static object @Lock = new object();
    
            /// <summary>
            /// 发送数据到服务器端
            /// </summary>
            /// <param name="Assemply">服务端程序集名称,如:Cn100.Wcf.Duplex.Service.CallbackService,Cn100.Wcf.Duplex.Service</param>
            /// <param name="method">调用方法名称,如:SendData</param>
            /// <param name="parameters">调用方法参数</param>
            public void SendData(string assembly, string method, params object[] parameters)
            {
                object[] paras=new object[parameters.Length];
                for (int i = 0; i < parameters.Length; i++)
                {
                    paras[i] = SerializeHelper.SerializeObject(parameters[i]);
                }
                lock (@Lock)
                {
                    try
                    {
                        if (channelFactory == null || channelFactory.State != CommunicationState.Opened)
                        {
                            channelFactory = CreateChannel<ICallbackService>("CallBackService", new ClientHandler());
                        }
                        ICallbackService proxy = channelFactory.CreateChannel();
                        proxy.SendData(assembly, method, paras);
                        Console.Read();
                    }
                    catch (Exception ex)
                    {
                        channelFactory = null;
                        //throw ex;
                    }
                }
            
           
                //using (DuplexChannelFactory<ICallbackService> channelFactory = new DuplexChannelFactory<ICallbackService>(instanceContext, "CallBackService"))
                //{
                //    ICallbackService proxy = channelFactory.CreateChannel();
                //    using (proxy as IDisposable)
                //    {
                //        ShowProcess();
                //        proxy.SendData(assembly, method, paras);
                //        Console.Read();
                //    }
                    
                //}
            }
    
            /// <summary>
            /// 异步调用发送数据
            /// </summary>
            /// <param name="assembly"></param>
            /// <param name="method"></param>
            /// <param name="parameters"></param>
            public void AsySendData(string assembly, string method, params object[] parameters)
            {
                Action<string, string,object[]> action = (ass, m, p) => SendData(ass, m, p);
                action.BeginInvoke(assembly, method, parameters, ar => action.EndInvoke(ar), null);
            }
    
    
            public DuplexChannelFactory<T> CreateChannel<T>(string name,object handler)
            {
                InstanceContext instanceContext = new InstanceContext(handler);
                DuplexChannelFactory<T> factory = new DuplexChannelFactory<T>(instanceContext, name);
    
                //EndpointAddress address = new EndpointAddress("net.tcp://127.0.0.1:9998/CallbackService");
                //NetTcpBinding binding = new NetTcpBinding();
               
                //ContractDescription description=new ContractDescription(name);
                //ServiceEndpoint potion=new ServiceEndpoint (description,binding,address);
                //DuplexChannelFactory<T> factory = new DuplexChannelFactory<T>(instanceContext, potion);
                
                return factory;
            }
    
            public void Dispose()
            {
                if (channelFactory != null)
                {
                    channelFactory.Close();
                    channelFactory = null;
                }
            }
    
        }
    }
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Cn100.Wcf.Duplex.Client
    {
        interface IClientHandler
        {
            /// <summary>
            /// 显示进度条
            /// </summary>
            void ShowProcess();
    
            /// <summary>
            /// 隐藏进度条
            /// </summary>
            void HideProcess();
    
            /// <summary>
            /// 发送数据到服务器端
            /// </summary>
            /// <param name="Assemply">服务端程序集名称,如:Cn100.Wcf.Duplex.Service.CallbackService,Cn100.Wcf.Duplex.Service</param>
            /// <param name="method">调用方法名称,如:SendData</param>
            /// <param name="parameters">调用方法参数</param>
            void SendData(string assembly, string method, params object[] parameters);
    
    
        }
    }
    


    协议:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    
    namespace Cn100.Wcf.Duplex.Contract
    {
    
        [ServiceContract(Namespace = "http://www.cn100.com", CallbackContract = typeof(ICallback),SessionMode=SessionMode.Required)]
        public interface ICallbackService
        {
    
            /// <summary>
            /// 发送数据到服务器端
            /// </summary>
            /// <param name="Assemply">服务端程序集名称,如:Cn100.Wcf.Duplex.Service.CallbackService,Cn100.Wcf.Duplex.Service</param>
            /// <param name="method">调用方法名称,如:SendData</param>
            /// <param name="parameters">调用方法参数</param>
            [OperationContract(IsOneWay = true)]
            void SendData(string Assemply, string method, params object[] parameters);
        }
    }
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    
    namespace Cn100.Wcf.Duplex.Contract
    {
       [ServiceContract]
       public interface ICallback
        {
           /// <summary>
           /// 客户端接收数据
           /// </summary>
           /// <param name="result"></param>
           /// <param name="count"></param>
           /// <param name="isComplete"></param>
           [OperationContract(IsOneWay = true)]
           void ReceiveData(object result, int count, int index, bool isComplete);
    
        }
    }
    

    服务端

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    using System.Reflection;
    using System.Diagnostics;
    using System.Runtime.Serialization;
    using System.IO;
    using System.Text.RegularExpressions;
    
    using Cn100.Wcf.Duplex.Contract;
    using Cn100.Wcf.Duplex.Module;
    using System.Runtime.Serialization.Formatters.Binary;
    using Cn100.Wcf.Duplex.Common;
    
    
    
    namespace Cn100.Wcf.Duplex.Service
    {
        [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
        public class CallbackService:ICallbackService
        {
    
            public void SendData(string assembly, string method, params object[] parameters)
            {
                try
                {
                    string strPath = System.Environment.CurrentDirectory;
    
                    string[] assemplys = assembly.Split(',');
    
                    string strClass = assemplys[0];
                    string strDLL = strPath + "/" + assemplys[1] + ".dll";
    
    
                    Assembly ass = Assembly.LoadFile(strDLL);
                    Type type = ass.GetType(strClass);
                    MethodInfo mi = type.GetMethod(method);
                    object obj = ass.CreateInstance(strClass);
    
                    object[] paras = new object[parameters.Length];
                    for (int i = 0; i < parameters.Length; i++)
                    {
                        paras[i] = SerializeHelper.DeserializeObject(parameters[i]);
                    }
    
                    object result = mi.Invoke(obj, paras);
    
                    ICallback callback = OperationContext.Current.GetCallbackChannel<ICallback>();
                    if (result != null)
                    {
                        int intOut = 0;
                        if (paras.Length > 0)
                        {
                            string strOut = paras[paras.Length - 1].ToString();
                            int.TryParse(strOut, out intOut);
                        }
    
                        //序列化
                        string strResult = SerializeHelper.SerializeObject(result);
    
                        
                        string[] source = StingSplit.SplitData(strResult, Size);
                        for (int i = 0; i < source.Length; i++)
                        {
                            callback.ReceiveData(source[i], i, i, false);
                        }
                        callback.ReceiveData("", intOut, source.Length, true);
                    }
                    else
                    {
                        callback.ReceiveData(null, 0, 0, true);
                    }
                    
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    if (ex.InnerException != null)
                    {
                        Console.WriteLine(ex.InnerException.Message);
                    }
                    throw ex;
                }
            }
    
           
    
            const string TransferSizeConfigName = "transferSize";
            public static int Size = GetTransferSize();
    
            public static int GetTransferSize()
            {
                
                if (System.Configuration.ConfigurationManager.AppSettings[TransferSizeConfigName] != null)
                {
                    string strSize = System.Configuration.ConfigurationManager.AppSettings[TransferSizeConfigName].ToString();
                    int intSize = 0;
                    if (int.TryParse(strSize, out intSize))
                    {
                        return intSize;
                    }
                }
                return 20;
            }
        }
    }
    


    服务载体配置:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
    	<system.serviceModel>
    		<bindings>
    			<netTcpBinding>
    				<binding  name="DuplexBindingConfiguration"  openTimeout="00:30:00" receiveTimeout="01:30:00"  sendTimeout="01:30:00"  maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
    					<security mode="None" />
    					<readerQuotas  maxStringContentLength="6553600" maxArrayLength="6553600" />
    				</binding>
    			</netTcpBinding>
    		</bindings>
    		<behaviors>
    			<serviceBehaviors>
    				<behavior name="mybehavior">
    					<serviceDebug includeExceptionDetailInFaults="true"/>
    				</behavior>
    			</serviceBehaviors>
    		</behaviors>
    		<services>
    			<service name="Cn100.Wcf.Duplex.Service.CallbackService">
    				<endpoint address="net.tcp://127.0.0.1:9998/CallbackService" bindingConfiguration="DuplexBindingConfiguration"
    						  binding="netTcpBinding" contract="Cn100.Wcf.Duplex.Contract.ICallbackService" />
    			</service>
    		</services>
    	</system.serviceModel>
    	<!--传输大小配置,不通超过最大配置:8192-->
    	<appSettings>
    		<add key="transferSize" value="500"/>
    	</appSettings>
    </configuration>


    客户端配置:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
    	<system.serviceModel>
    		<bindings>
    			<netTcpBinding>
    				<binding  name="TicketBindingConfiguration"  openTimeout="00:30:00" receiveTimeout="01:30:00"  sendTimeout="01:30:00"  maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
    					<security mode="None" />
    					<readerQuotas  maxStringContentLength="6553600" maxArrayLength="6553600" />
    				</binding>
    			</netTcpBinding>
    		</bindings>
    		<client>
    			<endpoint name="CallBackService" bindingConfiguration="TicketBindingConfiguration"
    					   address="net.tcp://127.0.0.1:9998/CallbackService"
    					   binding="netTcpBinding"
    					   contract="Cn100.Wcf.Duplex.Contract.ICallbackService"/>
    		</client>
    		<!--address="net.tcp://192.168.0.8:5687/CallbackService"-->
    		<!--address="net.tcp://127.0.0.1:9998/CallbackService"-->
    	</system.serviceModel>
    </configuration>

    工具类:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.Serialization;
    using System.IO;
    using System.Runtime.Serialization.Formatters.Binary;
    
    using Newtonsoft.Json;
    using System.Diagnostics;
    
    namespace Cn100.Wcf.Duplex.Common
    {
        public class SerializeHelper
        {
    
            /// <summary>
            /// 反序列化对象
            /// </summary>
            /// <param name="source"></param>
            /// <returns></returns>
            public static object DeserializeObject(object source)
            {
                //Stopwatch watch = new Stopwatch();
                //watch.Start();
                IFormatter formatter = new BinaryFormatter();
                byte[] buffer = Convert.FromBase64String(source.ToString());
                MemoryStream stream = new MemoryStream(buffer);
    
                object obj = formatter.Deserialize(stream);
                stream.Flush();
                stream.Close();
    
                //long time = watch.ElapsedMilliseconds;
                //watch.Stop();
                //Console.WriteLine(time);
    
                return obj;
    
            }
    
            /// <summary>
            /// 序列化对象
            /// </summary>
            /// <param name="source"></param>
            /// <returns></returns>
            public static string SerializeObject(object source)
            {
                //Stopwatch watch = new Stopwatch();
                //watch.Start();
    
                IFormatter formatter = new BinaryFormatter();
                MemoryStream stream = new MemoryStream();
                formatter.Serialize(stream, source);
                stream.Position = 0;
                byte[] buffer = new byte[stream.Length];
                stream.Read(buffer, 0, buffer.Length);
                stream.Flush();
                stream.Close();
    
                string strResult = Convert.ToBase64String(buffer);
    
                //long time = watch.ElapsedMilliseconds;
                //watch.Stop();
                //Console.WriteLine(time);
                return strResult;
    
            }
    
            public static string SerializeObjectToJson(object source)
            {
                return JsonConvert.SerializeObject(source);
            }
    
            public static object DeserializeJsonToObject(string source)
            {
                return JsonConvert.DeserializeObject(source);
            }
    
            public static List<T> DeserializeJsonToObject<T>(string source)
            {
                return JsonConvert.DeserializeObject<List<T>>(source);
            }
        }
    }
    


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Text.RegularExpressions;
    
    namespace Cn100.Wcf.Duplex.Common
    {
        public class StingSplit
        {
            public static string[] SplitData(string source, int length)
            {
                List<string> lists = new List<string>();
    
                if (source.Length > length)
                {
                    Regex reg = new Regex(".{" + length.ToString() + "}", RegexOptions.Multiline | RegexOptions.IgnoreCase);
                    if (reg.IsMatch(source))
                    {
                        int i = 0;
                        foreach (var m in reg.Matches(source))
                        {
                            i++;
                            lists.Add(m.ToString());
                        }
                        if (i * length < source.Length)
                        {
                            lists.Add(source.Substring(i * length));
                        }
                    }
                }
                else
                {
                    lists.Add(source);
                }
                return lists.ToArray();
            }
        }
    }
    


  • 相关阅读:
    Kubernetes 部署 Kubernetes-Dashboard v2.0.0
    Kubernetes 部署 Metrics Server 获取集群指标数据
    内网终端安全建设(转)
    内网安全运营的逻辑体系架构(转)
    thinkphp5配置文件
    MySQL索引失效的几种情况
    workman使用
    长连接技术(Long Polling)
    php好文章的记录
    php类与对象得使用场景
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3174313.html
Copyright © 2020-2023  润新知