IChatCallback.cs的代码:
public interface IChatCallback
[OperationContract(IsOneWay=true)]
void MessageBroadcast(string msg);
IChatService.cs代码:
[ServiceContract(SessionMode=SessionMode.Required, CallbackContract=typeof(IChatCallback))]
public interface IChatService
[OperationContract(IsOneWay=true,IsInitiating=true)]
void Register();
[OperationContract(IsOneWay=true,IsInitiating=false)]
void Send(string message);
ChatService.cs代码:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single
public class ChatService : IChatService
List<string> messages = new List<string>();
List<IChatCallback> clients = new List<IChatCallback>();
public void Send(string message)
messages.Add(message);
foreach(var client in clients)
if (client != Callback)
client.MessageBroadcast(message);
IChatCallback Callback
return OperationContext.Current.GetCallbackChannel<IChatCallback>();
public void Register()
clients.Add(Callback);
class Program
static void Main(string[] args)
using(var host = new ServiceHost(typeof(ChatService)))
host.Open();
Console.WriteLine("聊天服务器运行 " + string.Join(", ", host.Description.Endpoints.Select(s => s.Address)));
Console.WriteLine("按任何一个键退出。");
Console.ReadKey();
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="WcfDuplexChat.ChatService">
<baseAddresses>
<add baseAddress="http://localhost:12000/"/>
</baseAddresses>
</host>
<endpoint address="ChatServer" binding="wsDualHttpBinding" contract="Contract.IChatService">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange">
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
ChatCallbackHandler.cs代码:
public class ChatCallbackHandler : Contract.IChatCallback, ChatService.IChatServiceCallback
public void MessageBroadcast(string msg)
Console.WriteLine(msg);
app.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<wsDualHttpBinding>
<binding name="WSDualHttpBinding_IChatService" />
</wsDualHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:12000/ChatServer" binding="wsDualHttpBinding"
bindingConfiguration="WSDualHttpBinding_IChatService" contract="ChatService.IChatService"
name="WSDualHttpBinding_IChatService">
<identity>
<userPrincipalName value="simtex\Simon Pedersen" />
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>
Program.cs代码:
internal class Program
private static void Main(string[] args)
int port = 12001;
if (args.Length < 1)
Console.WriteLine("输入端口号:");
port = int.Parse(Console.ReadLine());
port = int.Parse(args[0]);
var instanceContext = new InstanceContext(new ChatCallbackHandler());
var binding = new WSDualHttpBinding();
binding.ClientBaseAddress = new Uri(string.Format("http://localhost:{0}/ChatClient", port));
var endpoint = new EndpointAddress("http://localhost:12000/ChatServer");
using (var factory = new DuplexChannelFactory<Contract.IChatService>(instanceContext, binding, endpoint))
var client = factory.CreateChannel();
client.Register();
Console.WriteLine("聊天客户端准备运行: " + binding.ClientBaseAddress);
var message = Console.ReadLine();
client.Send(message);
} while (true);
catch (Exception ex)
Console.Write(ex.ToString());
Console.ReadKey();
项目运行结果如图:
没有见过地狱的眼睛,永远也看不到光明IChatCallback.cs的代码: //由于回调契约本质也是一个服务契约,所以定义方式和一般意义上的服务契约基本一样。有一点不同的是,由于定义IChatService的时候已经通过[ServiceContract(CallbackContract=typeof(IChatCallback))]指明ICallback是一个服务契约了,所以ICallback不再
双工(Duplex)模式的消息交换方式体现在消息交换过程中,参与的双方均可以向对方发送消息。基于双工MEP消息交换可以看成是多个基本模式下(比如请求-回复模式和单项模式)消息交换的组合。双工MEP又具有一些变体,比如典型的订阅-发布模式就可以看成是双工模式的一种表现形式。双工消息交换模式使服务端回调(Callback)客户端操作成为可能。
在Wcf中不是所有的绑定协议都支持回调操作,Ba...
WCF的双工通信是指客户端和服务端都可以主动呼叫对方。在这种通信模式中,WCF利用双向绑定实现服务端和客户端相互公开终结点的信息。
在VS2015,.NET环境下进行测试
本章最大感悟是代理类必须是一个纯的代理类,即不应该有任何属性。
(1)打开WebConfig修改服务端的配置,应选择一个支持双工通信即会话的绑定(一般为wsDualHttpbinding和netTCPbin
SignalR和WCF都可以用于双工通信,但它们具有不同的优缺点。
SignalR是一种轻量级的跨平台实时通信框架,它可以在Web应用程序和移动应用程序之间实现实时通信。它使用WebSockets、Server-Sent Events(SSE)和长轮询等技术来提供实时通信服务。SignalR具有以下优点:
1. 高效性:SignalR使用WebSockets技术可以实现高效的双向通信,可以在客户端和服务器之间传输数据,而不需要频繁地发送HTTP请求。
2. 跨平台:SignalR可以在多个平台上运行,包括Windows、Linux、macOS等,可以在Web应用程序和移动应用程序之间实现实时通信。
3. 简单易用:SignalR的API简单易用,可以快速开始构建实时应用程序。
WCF是一种基于SOAP协议的通信框架,它可以用于构建分布式应用程序。WCF可以实现双工通信,但是相对于SignalR来说,它有以下缺点:
1. 复杂性:WCF的配置和使用相对比较复杂,需要进行大量的配置才能实现双工通信。
2. 性能:WCF使用SOAP协议进行通信,相对于SignalR来说,它的性能较低。
综上所述,如果需要构建实时通信应用程序,SignalR是更好的选择。如果需要构建分布式应用程序,并且对性能和可扩展性要求较高,可以考虑使用WCF。