rainit2006 / C-Program

C# Program knowledge
0 stars 0 forks source link

WCF #24

Open rainit2006 opened 7 years ago

rainit2006 commented 7 years ago

rainit2006 commented 7 years ago

WCFには、3種類の通信方法があります。

要求/応答パターン 一方向通信パターン 双方向通信パターン(非同期)

rainit2006 commented 7 years ago

http://www.cnblogs.com/iamlilinfeng/archive/2012/09/25/2700049.html

在WCF中的接口与普通接口的区别只在于两个上下文 [ServiceContract] :来说明接口是一个WCF的接口,如果不加的话,将不能被外部调用。 [OperationContract]:来说明该方法是一个WCF接口的方法,不加的话同上。

WCF has a multi-layered architecture namely Contracts layer, Service Runtime Layer, Messaging Layer and Activation and Hosting Layer.

Features of WCF can be described as follows:

rainit2006 commented 7 years ago

NamedPipe 1, 新建一个“WcfServiceLibrary1” 项目

- App.config (也可以不设定,这样需要在server host端的代码里实现)
``` build工程 ,生成dll文件。 2,追加创建一个Windows Console项目,然后Add Reference里追加WcfServiceLibrary1, 并相应地Add Reference里追加System.ServiceModel库 - program.cs的Main函数里 ``` ServiceHost host = new ServiceHost(typeof(WcfServiceLibrary1.Service1), new Uri("net.pipe://localhost/WcfServiceLibrary1/Service1/")); try { //host.AddServiceEndpoint(typeof(WcfServiceLibrary1.IService1), new NetNamedPipeBinding(), "IService1"); //如果WcfServiceLibrary1里的app.config没有指定service属性的话,则需要在代码里实现。 host.Open(); // The service can now be accessed. Console.WriteLine("The service is ready."); Console.WriteLine("Press to terminate service."); Console.WriteLine(); Console.ReadLine(); } ``` 此时Debug程序,则可以弹出server端 。 注意: WcfServiceLibrary1的工程属性里“WCF options”里如果下图checkbox选中的话,则它会创建server导致program.cs的server无法生成(弹出error说,有其它服务在listerning相同的base address) ![image](https://user-images.githubusercontent.com/12871721/30269693-baef5eac-9724-11e7-978b-d6eea74e37b3.png) 3, 创建client端 添加Windows form工程,工程里追加IService1.cs文件。在form1.cs里添加button和textbox。 在form1.cs里, ``` private void button1_Click(object sender, EventArgs e) { EndpointAddress endPointAddr = new EndpointAddress("net.pipe://localhost/WcfServiceLibrary1/Service1/"); //NetNamedPipeBinding namedPipe = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None); ChannelFactory channel = new ChannelFactory(new NetNamedPipeBinding()); IService1 service = channel.CreateChannel(endPointAddr); textBox1.Text = service.sayHello(); } ``` 为了Debug时同时让Server和Client都启动,需要进行下面设定。 ![image](https://user-images.githubusercontent.com/12871721/30308819-c5dd06fe-97c2-11e7-9ebf-c54c083a6359.png)
rainit2006 commented 7 years ago

双方向コントラクト

Server端代码

  [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
    public class Service1 : IService1
    {
        public ISendDataCallBack callback = null;

        public Service1()
        {
            callback = OperationContext.Current.GetCallbackChannel<ISendDataCallBack>();
        }

        public void GetData(int value)
        {
            // string.Format("You entered: {0}", value);
        }

        public void sayHello(string data)
        {
            callback = OperationContext.Current.GetCallbackChannel<ISendDataCallBack>();
            Console.WriteLine(data);
            callback.getCallback("Hello, this is server.");

            return;
        }
}

Server Host端代码

 static void Main(string[] args)
        {
            //NetNamedPipeBinding namedPipe = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
            ServiceHost host = new ServiceHost(typeof(WcfServiceLibrary1.Service1),
                new Uri("net.pipe://localhost/WcfServiceLibrary1/Service1"));
            try
            {
                //host.AddServiceEndpoint(typeof(WcfServiceLibrary1.IService1), new NetNamedPipeBinding(), "IService1");

                // Open the service host to accept incoming calls  
                host.Open();

                // The service can now be accessed.  
                Console.WriteLine("The service is ready.");

                Console.WriteLine("Press <ENTER> to terminate service.");
                Console.WriteLine();
                Console.ReadLine();

                // Close the ServiceHostBase to shutdown the service.  
                host.Close();
            }

Client

  class ClientProgram : ISendDataCallBack
    {
        public string message = "null";
        public IService1 channel = null;

        public void getCallback(string data)
        {
            message = data;
            Console.WriteLine(message);
        }
    }

Client host端代码

 static void Main(string[] args)
        {
            ClientProgram client = new ClientProgram();

            Thread.Sleep(5000);

            //client.Create();
            DuplexChannelFactory<WcfServiceLibrary1.IService1> factory = new DuplexChannelFactory<WcfServiceLibrary1.IService1>(new InstanceContext(client));
            factory.Endpoint.Binding = new NetNamedPipeBinding();
            factory.Endpoint.Contract.ContractType = typeof(WcfServiceLibrary1.IService1);
            factory.Endpoint.Address = new EndpointAddress("net.pipe://localhost/WcfServiceLibrary1/Service1");

            var channel = factory.CreateChannel();

            channel.sayHello("client");

            Console.WriteLine(client.message);
            Console.Read();

        }

注意: Debug的时候 Client程序经常报 错说,没有找到endpoint。所以不建议通过visual studio同时启动server host和client host,而是从debug/bin目录里先启动server host再 通过visual studio单独调试client端比较好。

rainit2006 commented 7 years ago

利用DuplexBase

主要是更改client端,生成两个class。

 class ClientProgram : DuplexClientBase<IService1>, IService1
    {

        public IService1 channel = null;

        public ClientProgram(InstanceContext callbackCntx)
            : base(callbackCntx, new NetNamedPipeBinding(), 
                  new EndpointAddress("net.pipe://localhost/WcfServiceLibrary1/Service1"))
        {

        }

        public void GetData(int data)
        {
            base.Channel.GetData(data);
        }

        public void sayHello(string data)
        {
            base.Channel.sayHello(data);
        }

    }

    class clientCallback : ISendDataCallBack
    {
        public string message = "null";
        public void getCallback(string data)
        {
            message = data;
            Console.WriteLine(message);
        }
    }

client host端

  static void Main(string[] args)
        {
            clientCallback callback = new clientCallback();
            InstanceContext cntx = new InstanceContext(callback);

            ClientProgram proxy = new ClientProgram(cntx);
            proxy.sayHello("client proxy");

            Console.WriteLine(callback.message);
            Console.Read();

        }
rainit2006 commented 6 years ago

ClientBase クラス Provides the base implementation used to create Windows Communication Foundation (WCF) client objects that can call services.