项目结构:

客户端:

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();
}
}
}

WCF全双工数据传输的更多相关文章

  1. wcf,socket,数据传输方式

    WCF的最终目标是通过进程或不同的系统.通过本地网络或是通过Internet收发客户和服务之间的消息. WCF合并了Web服务..net Remoting.消息队列和Enterprise Servic ...

  2. WCF 字节数据传输

    准备工作 1.新建一个工程,添加一个WCF服务库, 然后公共的类库, 添加一个默认可序列化的的CompositeType类用于压缩. [Serializable] public class Compo ...

  3. WCF全双工通信实例分享(wsDualHttpBinding、netTcpBinding两种实现方式)

    最近在研究WCF通信,如果没有接触过的可以看我的前一篇文章:https://www.cnblogs.com/xiaomengshan/p/11159266.html 主要讲的最基础的basicHttp ...

  4. 在 WCF 中使用高效的 BinaryFormatter 序列化

    本文将定义一个 WCF 终结点行为扩展,以在 WCF 中使用更高效的 BinaryFormatter 进行二进制序列化,并实现对是否使用传统二进制序列化功能的可配置. 介绍 实现步骤 使用方法 效果 ...

  5. 解决WCF大数据量传输 ,System.Net.Sockets.SocketException: 远程主机强迫关闭了一个现有的连接

    开发中所用的数据需要通过WCF进行数据传输,结果就遇到了WCF大量传输问题 也就是提示System.Net.Sockets.SocketException: 远程主机强迫关闭了一个现有的连接 网上解决 ...

  6. 转:wcf大文件传输解决之道(2)

    此篇文章主要是基于http协议应用于大文件传输中的应用,现在我们先解析下wcf中编码器的定义,编码器实现了类的编码,并负责将Message内存中消息转变为网络发送的字节流或者字节缓冲区(对于发送方而言 ...

  7. 基于WCF 的远程数据库服务访问技术

    原文出处:http://www.lw80.cn/shuji/jsjlw/13588Htm.Htm摘要:本文介绍了使用WCF 建立和运行面向服务(SOA)的数据库服务的系统结构和技术要素,分析了WCF ...

  8. 将WCF迁移到gRPC

    使用protobuf-net.Grpc将WCF服务迁移到gRPC非常简单.在这篇博文中,我们将看看它到底有多简单.微软关于将WCF服务迁移到gRPC的官方指南只提到了Gooogle.Protobuf方 ...

  9. 【转】TCP/IP协议栈及OSI参考模型详解

    OSI参考模型 OSI RM:开放系统互连参考模型(open systeminterconnection reference model) OSI参考模型具有以下优点: 简化了相关的网络操作: 提供设 ...

随机推荐

  1. MonkenRunner通过HierarchyViewer定位控件的方法和建议(Appium/UIAutomator/Robotium姊妹篇)

    1. 背景 在使用MonkeyRunner的时候我们经常会用到Chimchat下面的HierarchyViewer模块来获取目标控件的一些信息来辅助我们测试,但在MonkeyRunner的官网上是没有 ...

  2. Android KitCat 4.4.2 ADB 官方所支持的所有Services格式翻译

    在之前的文章中有转帖网上同行制作的ADB协议表格<<adb概览及协议参考>>,但不够详尽,所以这里自己另外基于Android 4.4.2的技术文档重新做一次翻译. HOST S ...

  3. Arraylist、Linkedlist遍历方式性能分析

    本文主要介绍ArrayList和LinkedList这两种list的常用循环遍历方式,各种方式的性能分析.熟悉java的知道,常用的list的遍历方式有以下几种: 1.for-each List< ...

  4. 用一条SQL语句取出第 m 条到第 n 条记录的方法

    原文:用一条SQL语句取出第 m 条到第 n 条记录的方法   --从Table 表中取出第 m 条到第 n 条的记录:(Not In 版本)       *    FROM Table     id ...

  5. Elegant Box主题wpdb::prepare() 报错[已解决]

    整理书签,发现个网页,是解决Elegant Box主题与新版Wordpress3.5主题不兼容的(3.5改了一个函数的参数个数所致).记得当时使用NeoEase出的主题的时候两次遇到这个问题,费了点功 ...

  6. Mockito使用注意事项

    已使用mockito有些问题.例如:配合可变长度参数.定义自己的参数匹配,在这些mockito官方文件(http://docs.mockito.googlecode.com/hg/latest/org ...

  7. 【转】Android 图层引导帮助界面制作

    2012-11-02 10:31 1979人阅读 评论(0) 收藏 举报 原文:http://www.cnblogs.com/beenupper/archive/2012/07/18/2597504. ...

  8. TodoList开发笔记 – Part Ⅱ

    上一节给出了应用的两个主要UML类图,应用采用的技术也给出了,这一节开始实际设计编码 一.应用公开的方法 其实就几个的方法而已 1.代办事项的CRUD 2.代办事项归类目录的CRUD 3.代表事项“已 ...

  9. Javascript多线程引擎(十)---Web服务器

     Javascript多线程引擎(十)---Web服务器 经过一天的努力, 引擎可以支持web服务的功能了并且支持UTF-8的编码, 具有对HTTP参数的解析,状态码的配置, 响应报文的输出等. 提供 ...

  10. Jetbrains 系列神器

    PRODUCTS IntelliJ IDEA ReSharper WebStorm PhpStorm PyCharm RubyMine AppCode YouTrack TeamCity dotTra ...