终结点主要作用是向客户端公开一些信息入口,通过这个入口,可以找到要调用的服务操作。通常,终结点会使用三个要素来表述,我记得老蒋(网名:Artech,在园子里可以找到他)在他有关WCF的书里,把这三要素称为“ABC”。

A就是Address,就是终结点的地址;B是Binding,绑定,用于描述传输的协议、是否启用安全模式等;C是Contract,即服务协定。

一个服务协定可以由多个终结点公开,比如一个终结点可能使用HTTP协议,另一个则使用TCP等。

WCF是否真的像某些人说的那么复杂难学呢?依老周的低见,是比其他方面的东东稍稍难了些,主要是内容涉及面广,但是,绝不像某些谣言说的那么恐怖。从老周的低劣水平来看,肯定比C++好学(当然了,那不是一回事,C++是练内功的)。编程学习的过程中肯定会遇到难关的,这是必然现象,你不能逃避,你如果想逃避,我建议你还是学学如何被大款们包养吧。

如果你希望你这辈子学有所成,能做些事情,将来起码可以在你的后代面前吹牛的话,不管你学什么,做哪一行,都不可能会轻松的。你要真想不劳而获,想过得轻松,那行,就找个大款包养你吧,这世界上做什么都苦,只有做贱人是最快活的。

提到了C++,自然也包括C,我就想到一个事:常有人问,零基础编程学什么,我可以肯定地回答你,从C开始。不管你将来用不用C,都应该去学,基础不打好,以后你就会付出代价的。

好了,P话说多了。关于WCF怎么学,如果你胆子够大,来来来,听听老周的学习方法。其实,当老周遇到难学的东西时,第一件事就是把各种理论和概念全扔一边,并且无视其存在,然后专心于代码,反正先别管它是什么东西,学会了代码怎么写,再回过头去看那些概念啊,理论啊什么的。反正老周不太喜欢概念性的东西,说得玄乎又玄,看都看不懂,还故意装逼,弄得连语义都不通畅,朗读起来还特别的别扭。

那些搞理论的人,似乎喜欢卖弄。老周向来喜欢简单易懂的东西,最好说得连小娃娃都能听得懂,那才叫牛逼,难道不是吗?人家爱因斯坦那么NB的人了,都学着尝试给一老太太讲他的研究成果。

唉,又说了一段F话,现在进入主题,今天咱们聊聊终结点的监听地址。

通常,我们在定义终结点的时候,会通过Address属性指定一个地址,客户端通过这个地址可以找到对应的服务操作,这样才能与服务器通信。这好比你让你朋友来你家玩,你总得告诉他你住哪里,只要有地址,哪怕他拿着手机开着GPS也能找到你,不然的话,难道你让他发寻人启事来找你不成?

直接设置终结点的Address属性,你必须指定一个有效的真实地址,如果在服务中指定了基址,那么终结点可以用相对地址,前提是,终结点的地址要与基址的协议相同,比如,都是HTTP。

协议、主机(端口)是必须是真实的,至于后面的路径,可以随便,比如这样:

http://192.168.1.7:8888/worker/sendout/

http://192.168.1.7:8888/feedback/

HTTP是协议,要明确;192.xxx.xxx.xxx:8888是主机和端口,要真实,不然客户端找不到。而后面的/.../..是可以随意指定,这些路径只用于标识终结点。

但是,你会注意到,终结点还有一个属性叫ListenUri,这又是啥呢?这个东东是服务器用来监听客户端请求的地址,必须是真实的地址。那么,监听地址和Address又是啥关系呢?

如果只指定了Address,而没有指定ListenUri,那么,Address必须是真实的地址,服务器就会以Address作为监听地址,从此地址接收客户端连接。即Address和ListenUri相同。

如果明确指定了ListenUri,服务就会在此地址上监听客户端连接,Address值既可以用一个真实地址,也可以用一个非真实地址。在这种情况下,Address成了逻辑地址,仅用来标识这个终结点而已。

比如,我设置了ListenUri为:http://DogPC:80/in/,

然后,Address就可以这样http://DogPC:1122/wang_wang/,也可以这样:http://fuck.org。这时候,Address的地址可以是不存在的,不信你上网查查,哪个网站会叫fuck.org。

但是,你得注意了,就算Address成了逻辑地址,它的协议必须与ListenUri的协议相同。如果监听地址是http,那么逻辑地址也要是http,如果监听地址是net.tcp://www.垃圾.com/getcue,你设置逻辑地址为http://mouse.net,这样是不可以的,因为监听地址的协议是net.tcp,所以逻辑地址也必须是net.tcp协议。

这么一来,监听地址就成了“中转站”,服务在此处监听连接,一旦有客户端请求,就会接收,然后它不会对收到的消息进行处理,它会把消息调度到专门的通道(Channel)进行处理。说白了就是:监听地址只负责收信,不负责拆信看信和回信

这让老周想起上大学的时候,我们学校有一个专门的点(ListenUri),快递员来了统一到这个点,那里有老师和学生值班,统一收件,然后会打电话给某位同学,或者到某栋宿舍某室通知你,有快件,你去拿吧。

假如,老周当年雄心勃勃地准备去考研,于是和几位同学一起,在网上订了几本复习资料。书到了之后,快递员会拿到那个点,那里有老师专门收件,但老师只负责收件,至于里面的东西如何就不管了。然后老师会通知老周,请到大厅收发处取件。于是老周骑着九年前买的自行车,飞到大厅,取回物件,回到宿舍再拆包。

下面,咱们来看个例子,服务协定和服务类的定义就不发了,这些相信大家都懂,咱们看看服务器的终结点配置。

      <service name="sv">
<endpoint address="http://supperman.org" contract="add" listenUri="http://localhost:6000/input" listenUriMode="Explicit" binding="netHttpBinding"/>
<endpoint address="http://supperegg.org" contract="sub" binding="netHttpBinding" listenUri="http://localhost:6000/input" />
</service>

supperman.org和supperegg.org都是假的地址,压根儿没这域名,之所以Address可以这么配置,是因为我为两个终结点设置了listenUri,监听的地址必须是真实的。对了,listenUriMode最好使用默认值,即Explicit,这样做是方便客户端配置;如果用的值是Unique,就会在监听地址后面添加一个GUID作为后缀,关键是这个GUID每次运行服务都会重新生成,每次都不同,这不方便客户端配置。当然了,它也是有用的,如果要区分两个地址的话,可以让它唯一,或者你干脆换个端口。

大家可能发现了,两个终结点使用的是相同的监听地址。listenUri是可以多个终结点共用的,因为它只负责收消息,而不处理消息,它只起到转发的作用。但是,address是不能相同的,因为它要用来作为终结点的标识,更何况,前面讲过的ABC,如果两个终结点的ABC都相同,那没什么意义。

在客户端,终结点的address、binding、contract也要与服务器匹配。

    <client>
<endpoint name="epadd" address="http://supperman.org" contract="add" binding="netHttpBinding" behaviorConfiguration="bv"/>
<endpoint address="http://supperegg.org" contract="sub" binding="netHttpBinding" name="epsub" behaviorConfiguration="bv"/>
</client>

由于刚才在服务器上,address成了逻辑地址,而不是真实的地址,所以必须配置它的Behavior,加入ClientVia行为,以指定真实的地址。

      <endpointBehaviors>
<behavior name="bv">
<clientVia viaUri="http://localhost:6000/input"/>
</behavior>
</endpointBehaviors>

ViaUri必须填上服务的监听地址。

然后,可以尝试调用一下。

            using (ChannelFactory<CommonContracts.IAddCompute> fac1 = new ChannelFactory<CommonContracts.IAddCompute>("epadd"))
using (ChannelFactory<CommonContracts.ISubCompute> fac2 = new ChannelFactory<CommonContracts.ISubCompute>("epsub"))
{
CommonContracts.IAddCompute channel1 = fac1.CreateChannel();
CommonContracts.ISubCompute channel2 = fac2.CreateChannel();
int r1 = channel1.Add(, );
int r2 = channel2.Sub(, );
Console.WriteLine($"结果1:{r1}\n结果2:{r2}"); Console.Read();
}

现在,我们对比一下。

先看客户端发出的请求消息。

然后,再看看服务器收到的请求消息。

两条消息内容一样,但你细心看,就会发现,服务器收到消息后对消息进行了更改,多加了一个 To 消息头,这个消息头的内容和终结点的逻辑地址(Address)相同,这样就相当于在监听地址收到请求消息,然后转发到终结点对应的通道进行处理。

好了,今天的烂文写完了,怎么样,不算难吧。

示例源代码下载地址

【WCF】终结点的监听地址的更多相关文章

  1. WCF-ServiceEndpoint的监听地址与监听模式

    ServiceEndpoint具有一个可读可写的ListenUri属性,该属性表示服务端终结点的物理监听地址,该地址默认和终结点逻辑地址一致(即ServiceEndpoint的Uri).对于客户端来说 ...

  2. Linux下修改Oracle监听地址

    如果你的服务器换了ip怎么办? 如果你的服务器换了名字怎么办? 以前的小伙伴怎么办? 以前的老客户怎么办? 没关系,简单教你修改监听地址,老朋友随便找! 想要修改监听地址首先要找到两个文件,确定两样东 ...

  3. ASP.NET Core 发布之后通过命令控制监听地址和环境变量

    添加Command支持 新建一个ASP.NET Core 项目,打开Program.cs 添加下面的代码: public class Program { public static void Main ...

  4. 关于.net core 在docker中监听地址设置踩坑记

    1.今天在做docker容器的时候发现如果将.net core 内部监听地址设置为localhost:8888. 2.在docker build -p 6444:8888 运行容器后,外部通过6444 ...

  5. WCF终结点——终结点地址(EndpointAddress)

    终结点的地址的Uri属性作为终结点地址的唯一标示. 包括客户端终结点和服务端终结点. 一.服务端终结点: 服务端的终结点通过宿主的添加方法暴露出来,从而成为可以调用的资源. 下面是将服务绑定到宿主的代 ...

  6. KestrelServer详解[1]:注册监听终结点(Endpoint)

    具有跨平台能力的KestrelServer是最重要的服务器类型.针对KestrelServer的设置均体现在KestrelServerOptions配置选项上,注册的终结点是它承载的最重要的配置选项. ...

  7. 在 Windows Server Container 中运行 Azure Storage Emulator(一):能否监听自定义地址?

    我要做什么? 改 ASE 的监听地址.对于有强迫症的我来说,ASE 默认监听的是 127.0.0.1:10000-10002,这让我无法接受,所以我要将它改成域名 + 80 端口的方式: 放到容器中. ...

  8. Self Host模式下的ASP. NET Web API是如何进行请求的监听与处理的?

    构成ASP.NET Web API核心框架的消息处理管道既不关心请求消息来源于何处,也不需要考虑响应消息归于何方.当我们采用Web Host模式将一个ASP.NET应用作为目标Web API的宿主时, ...

  9. 学习ASP.NET Core, 怎能不了解请求处理管道[3]: 自定义一个服务器感受一下管道是如何监听、接收和响应请求的

    我们在<服务器在管道中的"龙头"地位>中对ASP.NET Core默认提供的具有跨平台能力的KestrelServer进行了介绍,为了让读者朋友们对管道中的服务器具有更 ...

随机推荐

  1. 在.NET Core 里使用 BouncyCastle 的DES加密算法

    .NET Core上面的DES等加密算法要等到1.2 才支持,我们可是急需这个算法的支持,文章<使用 JavaScriptService 在.NET Core 里实现DES加密算法>需要用 ...

  2. java中servlet的各种路径

    1. web.xml中<url-pattern>路径,(叫它Servlet路径!) > 要么以“*”开关,要么为“/”开头 2. 转发和包含路径 > *****以“/”开头:相 ...

  3. 《JavaScript设计模式与开发实践》整理

    最近在研读一本书<JavaScript设计模式与开发实践>,进阶用的. 一.高阶函数 高阶函数是指至少满足下列条件之一的函数. 1. 函数可以作为参数被传递. 2. 函数可以作为返回值输出 ...

  4. Python学习

    Python基础教程        网易云课堂-零基础入门学习Python

  5. php cryptr 加密函数

    class CryptHelper { /** * 加密 * @param unknown $password * @param unknown $salt * @return string */ p ...

  6. C#语法糖大汇总

    首先需要声明的是"语法糖"这个词绝非贬义词,它可以给我带来方便,是一种便捷的写法,编译器会帮我们做转换:而且可以提高开发编码的效率,在性能上也不会带来损失.这让java开发人员羡慕 ...

  7. Hadoop的安装与设置(1)

    在Ubuntu下安装与设置Hadoop的主要过程. 1. 创建Hadoop用户 创建一个用户,用户名为hadoop,在home下创建该用户的主目录,就不详细介绍了. 2. 安装Java环境 下载Lin ...

  8. 端盘子的服务生到月薪一万五的IT精英,你能相信吗

    一直以来,我都觉得自己不是一个有故事的人. 以前的我,是个乖宝宝,对父母言听计从,特别内向,甚至一度感觉到自卑.不上学之后,我干过送货员,去工地除泥搬砖,当过油漆工,去过工厂,还去饭店当过端盘子的服务 ...

  9. On cloud, be cloud native

    本来不想起一个英文名,但是想来想去都没能想出一个简洁地表述该意思的中文释义,所以就用了一个英文名称,望见谅. Cloud Native是一个刚刚由VMware所提出一年左右的名词.其表示在设计并实现一 ...

  10. .NET基础拾遗(6)ADO.NET与数据库开发基础

    Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开发基 ...