0

0

对wcf的理解--实现计算器功能

零下一度

零下一度

发布时间:2017-06-24 09:36:32

|

2049人浏览过

|

来源于php中文网

原创

wcf本质上提供一个跨进程、跨机器以致跨网络的服务调用 ,本示例中 主要实现了计算器的功能,大部分的函数来源于网上别人的帖子,这叫站在巨人的肩膀上,o(∩_∩)o哈哈~,但是为了加深自己的对wcf的理解,因此决定自己在写个类似的demo,把写demo中遇到的问题展现出来,我相信对于初识wcf的程序员了来说,也会遇到各种问题。好了步入正题。

WCF 分为四个部分 1、契约(Interface)2、服务契约(Service)3、WCF 宿主程序(控制台或者IIS) 4、客户端(Client)

本人在写wcf的时候喜欢将四个部分分别拆分成不同的类库来管理。

1、契约 

     契约是对外开放的接口,暴露给客户端的函数名称首先,新建一个wcf服务库,名称为Interface,如图所示:

删掉程序中默认的文件(App.config,IService1.cs,Service1.cs),新建ICalculator

namespace Interface
{
    [ServiceContract(Name = "CalculatorService", Namespace = "")]public interface ICalculator
    {
        [OperationContract]double Add(double x, double y);

        [OperationContract]double Subtract(double x, double y);

        [OperationContract]double Multiply(double x, double y);

        [OperationContract]double Divide(double x, double y);

    }
}

2、新建服务契约,其实就是实现契约的类 ,添加"新建项目"->WCF->"WCF服务库" (如 第一步新建契约是一样的步骤),类库的名称为Service,

新建成功后,删除默认文件(App.config,IService1.cs,Service1.cs),添加引用"Interface" 类库,新建CalculatorService 并实现ICalculator 

namespace Service
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]public class CalculatorService : ICalculator
    {public double Add(double x, double y)
        {return x + y;
        }public double Subtract(double x, double y)
        {return x - y;
        }public double Multiply(double x, double y)
        {return x * y;
        }public double Divide(double x, double y)
        {return x / y;
        }
    }

3、新建WCF宿主程序,WCF的契约和服务契约都已经建完,但是还需要一个程序来承载这些接口供外部程序调用,因此称之为宿主程序,宿主程序可以部署在IIS上,也可以用控制台程序运行方便调试,下面我就介绍用控制台程序作为宿主程序。在解决方案的名称右键添加"控制台程序" 名称为Hosting ,添加对Interface和Service的引用

实现wcf对外开放有两种方式,一种方式是配置文件,将所有的WCF信息都写到配置文件中

第一种:WCF的相关信息写到配置文件(App.config)中 



  
    
  
  
    
      
                  
        
        
        
        
        
        
          
            
            
          
        
      
    
    
      
        
          
          
        
      
    
  

 

 

Main方法的主要代码如下,

    public class Program
    {internal static ServiceHost host = null;static void Main(string[] args)
        {using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
            {

                host.Opened += delegate{
                    Console.WriteLine("CalculaorService已经启动,按任意键终止服务!");
                };
                host.Open();
                Console.ReadLine();
            }
        }
    }

运行控制台程序,如下图所示:

第二种:写一个WCFHelper类,添加帮助类的时候,一定引用System.Runtime.Serialization ,并且删掉App.config 对wcf的配置,否则会报错代码如下:

 public static class WCFHelper
    {public static string IP { get; set; }public static int Port { get; set; }static WCFHelper()
        {try{
                IP = System.Environment.MachineName;// ConfigurationManager.AppSettings["ServiceIP"];//                Port = int.Parse(ConfigurationManager.AppSettings["ServicePort"]);
            }catch{

            }

            EndpointAddress.Add(BindingProtocol.Http, "http://{0}:{1}/{2}/{3}");
            EndpointAddress.Add(BindingProtocol.NetTcp, "net.tcp://{0}:{1}/{2}/{3}");//EndpointAddress.Add(BindingProtocol.NetMsmq, "net.msmq://{0}:{1}/" + schema + "/{2}");//EndpointAddress.Add(BindingProtocol.NetPipe, "net.pipe://{0}:{1}/" + schema + "/{2}");try{
                httpBinding = new BasicHttpBinding();
                httpBinding.MaxBufferSize = 200065536;
                httpBinding.MaxReceivedMessageSize = 200065536;
                httpBinding.CloseTimeout = new TimeSpan(0, 10, 0);
                httpBinding.OpenTimeout = new TimeSpan(0, 10, 0);
                httpBinding.ReceiveTimeout = new TimeSpan(0, 10, 0);
                httpBinding.SendTimeout = new TimeSpan(0, 1, 0);

                httpBinding.Security.Mode = BasicHttpSecurityMode.None;

                httpBinding.ReaderQuotas.MaxDepth = 64;
                httpBinding.ReaderQuotas.MaxStringContentLength = 2147483647;
                httpBinding.ReaderQuotas.MaxArrayLength = 16384;
                httpBinding.ReaderQuotas.MaxBytesPerRead = 4096;
                httpBinding.ReaderQuotas.MaxNameTableCharCount = 16384;
            }catch{
                httpBinding = new BasicHttpBinding();
            }try{
                tcpBinding = new NetTcpBinding();
                tcpBinding.CloseTimeout = new TimeSpan(0, 1, 0);
                tcpBinding.OpenTimeout = new TimeSpan(0, 1, 0);
                tcpBinding.ReceiveTimeout = new TimeSpan(0, 10, 0);
                tcpBinding.SendTimeout = new TimeSpan(0, 1, 0);
                tcpBinding.TransactionFlow = false;
                tcpBinding.TransferMode = TransferMode.Buffered;
                tcpBinding.TransactionProtocol = TransactionProtocol.OleTransactions;
                tcpBinding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
                tcpBinding.ListenBacklog = 100000;
                tcpBinding.MaxBufferPoolSize = 524288;
                tcpBinding.MaxBufferSize = 200065536;
                tcpBinding.MaxConnections = 2000;
                tcpBinding.MaxReceivedMessageSize = 200065536;
                tcpBinding.PortSharingEnabled = true;

                tcpBinding.Security.Mode = SecurityMode.None;

                tcpBinding.ReaderQuotas.MaxDepth = 64;
                tcpBinding.ReaderQuotas.MaxStringContentLength = 2147483647;
                tcpBinding.ReaderQuotas.MaxArrayLength = 163840000;
                tcpBinding.ReaderQuotas.MaxBytesPerRead = 4096;
                tcpBinding.ReaderQuotas.MaxNameTableCharCount = 16384;

                tcpBinding.ReliableSession.Ordered = true;
                tcpBinding.ReliableSession.InactivityTimeout = new TimeSpan(0, 10, 0);
                tcpBinding.ReliableSession.Enabled = false;
            }catch{
                tcpBinding = new NetTcpBinding();
            }
        }private static BasicHttpBinding httpBinding;public static BasicHttpBinding HttpBinding
        {get{return httpBinding;
            }
        }private static NetTcpBinding tcpBinding;public static NetTcpBinding TcpBinding
        {get{return tcpBinding;
            }
        }public static EndpointAddress GetEndpointAddress(string ip, int port, string serviceSchema, string serviceName, BindingProtocol protocol)
        {string address = EndpointAddress[protocol];
            address = string.Format(address, ip, port, serviceSchema, serviceName);return new EndpointAddress(address);
        }public static EndpointAddress GetEndpointAddress(string serviceSchema, string serviceName, BindingProtocol protocol)
        {string address = EndpointAddress[protocol];
            address = string.Format(address, IP, Port, serviceSchema, serviceName);return new EndpointAddress(address);
        }public static Uri GetBaseAddress(string ip, int port, string serviceSchema, string serviceName, BindingProtocol protocol)
        {string address = EndpointAddress[protocol];

            address = string.Format(address, ip, port + 1, serviceSchema, serviceName);return new Uri(address);
        }public static Uri GetBaseAddress(string serviceSchema, string serviceName, BindingProtocol protocol)
        {string address = EndpointAddress[protocol];

            address = string.Format(address, IP, Port + 1, serviceSchema, serviceName);return new Uri(address);
        }private readonly static Dictionary EndpointAddress = new Dictionary();public enum BindingProtocol
        {
            Http = 1,
            NetTcp = 2,//NetPipe = 3,//NetMsmq = 4        }
    }

将 宿主程序中的main方法改成如下:

BJXSHOP网上购物系统 - 书店版
BJXSHOP网上购物系统 - 书店版

BJXSHOP购物管理系统是一个功能完善、展示信息丰富的电子商店销售平台;针对企业与个人的网上销售系统;开放式远程商店管理;完善的订单管理、销售统计、结算系统;强力搜索引擎支持;提供网上多种在线支付方式解决方案;强大的技术应用能力和网络安全系统 BJXSHOP网上购物系统 - 书店版,它具备其他通用购物系统不同的功能,有针对图书销售而进行开发的一个电子商店销售平台,如图书ISBN,图书目录

下载
    static void Main(string[] args)
        {
            WCFHelper.IP = "127.0.0.10";
            WCFHelper.Port = 9999;

            Uri httpUri = WCFHelper.GetBaseAddress(WCFHelper.IP, WCFHelper.Port, "Calculator", "Inspect", WCFHelper.BindingProtocol.Http);using (ServiceHost host = new ServiceHost(typeof(CalculatorService), httpUri))
            {
                host.AddServiceEndpoint(typeof(ICalculator), WCFHelper.TcpBinding, WCFHelper.GetEndpointAddress(WCFHelper.IP, WCFHelper.Port, "Calculator", "InspectService", WCFHelper.BindingProtocol.NetTcp).Uri.AbsoluteUri);
                ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();#if DEBUGbehavior.HttpGetEnabled = true;#elsebehavior.HttpGetEnabled = false;#endifhost.Description.Behaviors.Add(behavior);
                host.Opened += delegate{
                    Console.WriteLine("CalculaorService已经启动,按任意键终止服务!");
                };
                host.Open();

                Console.ReadLine();
            }
}

 

 

4、宿主程序建完了,WCF的所有锲约已经对外可以访问了,那现在需要建立Client 去调用wcf程序了 ,

首先,编译宿主程序Host,找到bin/debug/ Host.exe 右键管理员打开,如果如下图证明服务已经于宁

其次,在解决方案名称->右键添加Winform程序 新建WinForm 程序,添加"服务引用"

添加服务引用 (此引用方式,是以"3、添加宿主程序" ->"第二种 WCF帮助类的方式")

点击“转到” 系统发现WCF服务,如下图所示:

 

点击确定,就成功的将wcf的引用了,下面开始调用WCF的程序了,例如调用Add方法,代码如下:

 ServiceReference1.CalculatorServiceClient client = new ServiceReference1.CalculatorServiceClient();
            textBox3.Text = client.Add(double.Parse(textBox1.Text), double.Parse(textBox2.Text)).ToString();

到此为止,wcf程序已经完成的跑通了,记得 调试的时候已经把宿主程序和client程序同时运行。

如果闲麻烦,vs 支持同时启动多个项目,可以同时把client 和host同时启动

 

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

14

2026.01.30

c++ 字符串格式化
c++ 字符串格式化

本专题整合了c++字符串格式化用法、输出技巧、实践等等内容,阅读专题下面的文章了解更多详细内容。

9

2026.01.30

java 字符串格式化
java 字符串格式化

本专题整合了java如何进行字符串格式化相关教程、使用解析、方法详解等等内容。阅读专题下面的文章了解更多详细教程。

12

2026.01.30

python 字符串格式化
python 字符串格式化

本专题整合了python字符串格式化教程、实践、方法、进阶等等相关内容,阅读专题下面的文章了解更多详细操作。

4

2026.01.30

java入门学习合集
java入门学习合集

本专题整合了java入门学习指南、初学者项目实战、入门到精通等等内容,阅读专题下面的文章了解更多详细学习方法。

20

2026.01.29

java配置环境变量教程合集
java配置环境变量教程合集

本专题整合了java配置环境变量设置、步骤、安装jdk、避免冲突等等相关内容,阅读专题下面的文章了解更多详细操作。

18

2026.01.29

java成品学习网站推荐大全
java成品学习网站推荐大全

本专题整合了java成品网站、在线成品网站源码、源码入口等等相关内容,阅读专题下面的文章了解更多详细推荐内容。

19

2026.01.29

Java字符串处理使用教程合集
Java字符串处理使用教程合集

本专题整合了Java字符串截取、处理、使用、实战等等教程内容,阅读专题下面的文章了解详细操作教程。

3

2026.01.29

Java空对象相关教程合集
Java空对象相关教程合集

本专题整合了Java空对象相关教程,阅读专题下面的文章了解更多详细内容。

6

2026.01.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
SciPy 教程
SciPy 教程

共10课时 | 1.3万人学习

R 教程
R 教程

共45课时 | 5.8万人学习

SQL 教程
SQL 教程

共61课时 | 3.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号