WCF可以理解为WebService的升级版,
能够通过配置兼容WebService,同时又拥有一些WebService不具备的优势,比如:
上一篇中我们直接使用默认创建的模板尝试了一下WCF。我们这里再手动写一下。
(友情提示:可以跳过。)
一、创建 Server
直接新建命令行程序。
- Program.cs
这里需要添加引用System.ServiceModel
。
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Text;
using System.Threading.Tasks;
namespace Server
{
///
/// define a contract
///
[ServiceContract]
public interface IService
{
[OperationContract]
string TestMethod();
}
///
/// the service behavior
///
public class MyService : IService
{
public string TestMethod()
{
return "my service test method";
}
}
class Program
{
static void Main(string[] args)
{
// 基址URI,必须,HTTP方案
Uri baseURI = new Uri("http://localhost:8008/Service");
using (ServiceHost host = new ServiceHost(typeof(MyService), baseURI))
{
// 向服务器添终结点
WSHttpBinding binding = new WSHttpBinding();
// 这里不需要安全验证
binding.Security.Mode = SecurityMode.None;
host.AddServiceEndpoint(typeof(IService), binding, "my");
// 为了能让VS生成客户端代码,即WSDL文档,故要添加以下行为
ServiceMetadataBehavior mdBehavior = new ServiceMetadataBehavior()
{
HttpGetEnabled = true
};
host.Description.Behaviors.Add(mdBehavior);
//如果服务顺利启动,则提示,处理Opened事件
host.Opened += (sender, e) => Console.WriteLine("服务已启动。");
// 启动服务器
try
{
host.Open();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
// 为了让程序不往下执行而结束,故加上这句
Console.ReadKey();
// 关闭服务器
host.Close();
}
}
}
}
定义和实现服务协议。
[ServiceContract]
public interface ICalcService
{
[OperationContract]
void Add();
void Sub();
}
public class CalcService : ICalcService
{
public void Add()
{
Console.WriteLine("add");
}
public void Sub()
{
Console.WriteLine("sub");
}
}
SOAP 是基于 XML 的简易协议,可使应用程序在 HTTP 之上进行信息交换。
- 为何使用
目前的应用程序通过使用远程过程调用(RPC)在诸如 DCOM 与 CORBA 等对象之间进行通信,但是 HTTP 不是为此设计的。RPC 会产生兼容性以及安全问题;防火墙和代理服务器通常会阻止此类流量。
通过 HTTP 在应用程序间通信是更好的方法,因为 HTTP 得到了所有的因特网浏览器及服务器的支持。SOAP 就是被创造出来完成这个任务的。
默认的情况下WCF使用称之为数据协定序列化程序的序列化引擎对数据进行序列化和反序列化,所有的.NET Framework基元类型,如整型、字符串型,以及某些被视为基元的类型,
如DateTime、XmlElement不需要做其他工作就可以被序列化,并被视拥有默认的数据协定。
Simple Demo
消息协定的定义和数据协定很像,也是先写一个类,然后附加MessageContractAttribute,而对于类的成员(字段或属性,不管是公共的还是私有的)可以附加MessageHeaderAttribute或MessageBodyMemberAttribute。
如果你不喜欢用Socket来传文件,不妨试试WCF,WCF的流模式传输还是相当强大和相当实用的。
因为开启流模式是基于绑定的,所以,它会影响到整个终结点的操作协定。如果你不记得或者说不喜欢背书,不想去记住哪些绑定支持流模式,可以通过以下方法:
因为开启流模式,主要是设置一个叫 TransferMode 的属性,所以,你看看哪些 Binding 的派生类有这个属性就可以了。
TransferMode其实是一个举枚,看看它的几个有效值:
-
Buffered:缓冲模式,说白了就是在内存中缓冲,一次调用就把整个消息读/写完,也就是我们最常用的方式,就是普通的操作协定的调用方式;
-
StreamedRequest:只是在请求的时候使用流,说简单一点就是在传入方法的参数使用流,如 int MyMethod(System.IO.Stream stream);
-
StreamedResponse:就是操作协定方法返回一个流,如 Stream MyMethod(string file_name);
我们知道,在WCF中,客户端对服务操作方法的每一次调用,都可以被看作是一条消息。
可能我们还会有一个疑问:如何知道客户端与服务器通讯过程中,期间发送和接收的SOAP是什么样子。
当然,也有人是通过借助其他工具来抓取数据包来查看。那,有没有办法让程序自己输出相应的SOAP信息呢?当然有,正式本文讨论主题。
Session对象存储特定用户会话所需的属性及配置信息。
这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。
当用户请求来自应用程序的 Web 页时,如果该用户还没有会话,则 Web 服务器将自动创建一个 Session 对象。当会话过期或被放弃后,服务器将终止该会话。