• 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("
    ");
                }));
            }
    
            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("
    ");
            }
    
            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();
            }
        }
  • 相关阅读:
    OI中的小智慧
    洛谷 P2335 SDOI 2005 毒瘤 位图(也补上注释了)
    洛谷P4779 Dijkstra 模板
    洛谷 P1156 垃圾陷阱 谈论剪枝,非满分
    8/14考试 JWG
    一个好消息 JWG
    刷水题(一) JWG
    C语言运算符优先级从没像现在这样深刻体会
    cron 备忘
    CentOS
  • 原文地址:https://www.cnblogs.com/icoolno1/p/7301552.html
Copyright © 2020-2023  润新知