WCF 双向通讯实例-简易的聊天程序

源码下载

程序分四个部分:

1、原理

使用WCF的nettcp绑定。nettcp绑定类似原来的RPC,即.net remoting,只是在WCF提供统一协定,同一服务可以拥有多种客户端。

2、代码展示

代码部分分为契约、服务、服务端UI、客户端四个部分。

2.1、契约部分

定义服务的接口,一个提供服务,另一个提供回调。

服务端接口定义:

    [ServiceContract(
        Name = "SampleDuplexHello",
        Namespace = "http://microsoft.wcf.documentation",
        CallbackContract = typeof(IHelloCallbackContract),
        SessionMode = SessionMode.Required
      )]
    public interface IDuplexHello
    {
        /// <summary>
        /// 往服务端发送消息
        /// </summary>
        /// <param name="greeting"></param>
        [OperationContract(IsOneWay = true)]
        void Hello(string greeting);

        /// <summary>
        /// 让服务端缓存客户端
        /// </summary>
        [OperationContract]
        void Registor();
    }

服务端回调接口定义:

    /// <summary>
    /// 回调接口
    /// </summary>
    public interface IHelloCallbackContract
    {
        /// <summary>
        /// 向客户端推送消息
        /// </summary>
        /// <param name="responseToGreeting"></param>
        [OperationContract(IsOneWay = true)]
        void Reply(string responseToGreeting);
    }

 

2.2、服务实现部分

代码部分:

    public class DuplexHelloImpl : IDuplexHello, IBrocaster
    {
        private ConcurrentBag<IHelloCallbackContract> clients = new ConcurrentBag<IHelloCallbackContract>();


       。。。

        public void Hello(string greeting)
        {
            if (ServerInstance != null)
            {
                ServerInstance.Update(greeting);
            }
        }

        public void Registor()
        {            
            IHelloCallbackContract callerProxy
              = OperationContext.Current.GetCallbackChannel<IHelloCallbackContract>();
            if (!clients.Contains(callerProxy))
            {
                clients.Add(callerProxy);
            }
        }       
    }

配置部分:

  <system.serviceModel>
    <bindings>
      <netTcpBinding>
        <binding name="NewBinding0">
          <security mode="None"/>
        </binding>
      </netTcpBinding>
    </bindings>
    <services>

      <service name="WindowsFormsServer.DuplexHelloImpl">
        <endpoint address="net.tcp://localhost:909/hello" bindingConfiguration="NewBinding0" binding="netTcpBinding" contract="Contracts.IDuplexHello"/>

      </service>
    </services>
  </system.serviceModel>

启动部分:

      static void Main()
        {
            ServiceHost host = new ServiceHost(typeof(DuplexHelloImpl));
            host.Open();

          。。。
        }

 

2.3、服务端界面

 public partial class ServerForm : Form, IUpdater
    {
        public static IBrocaster ServiceInstance { get; set; }

        public ServerForm()
        {
            InitializeComponent();
        }

        public void Update(string content)
        {
            this.Invoke(new Action(() =>
            {
                this.textBox2.AppendText(content);
                this.textBox2.AppendText("\r\n");
            }));
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (!string.IsNullOrWhiteSpace(textBox1.Text))
            {
                if (ServiceInstance == null)
                {
                    MessageBox.Show("服务启动中,稍后再发!");
                    return;
                }
                ServiceInstance.Brocast(textBox1.Text);
                textBox1.Text = "";
            }
            else
                MessageBox.Show("回复内容不能为空!");
        }

        private void ServerForm_Load(object sender, EventArgs e)
        {
            //Service与主窗体非同步,因而需要等待
            Task.Run(() => {
                while (ServiceInstance == null)
                {
                    Thread.Sleep(50);
                }
                ServiceInstance.ServerInstance = this;
            });           
        }
    }

 

2.4、客户端界面

public partial class ClientForm : Form, IHelloCallbackContract
    {
        /// <summary>
        /// 定义为字段,以供重用。
        /// </summary>
        IDuplexHello client;
        public ClientForm()
        {
            InitializeComponent();
        }

        public void Reply(string responseToGreeting)
        {
            this.textBox2.AppendText(responseToGreeting);
            this.textBox2.AppendText("\r\n");
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (!string.IsNullOrWhiteSpace(textBox1.Text))
            {
                client.Hello(textBox1.Text);
                textBox1.Text = "";
            }
            else
                MessageBox.Show("回复内容不能为空!");

        }

        private void ClientForm_Load(object sender, EventArgs e)
        {
            //创建连接
            InstanceContext cxt = new InstanceContext(this);
            NetTcpBinding binding = new NetTcpBinding();
            binding.Security.Mode = SecurityMode.None;
            string url = "net.tcp://localhost:909/hello";
            DuplexChannelFactory<IDuplexHello> factory =
                new DuplexChannelFactory<IDuplexHello>(cxt, binding, url);

            client = factory.CreateChannel();
            client.Registor();
        }
    }

 

posted @ 2017-08-07 21:44  八爻老骥  阅读(415)  评论(0编辑  收藏  举报