WCF热门问题编程示例(1):WCF服务如何获得客户端IP地址信息

简介:
    今天新开了一个系列文章《WCF热门问题编程示例》:主要是针对WCF里比较有价值的问题的收集和整理,进行分析和  编程实践。最后会给出具体的示例代码。这个系列的第一篇文章:WCF热门问题编程示例(1):WCF服务如何获得客户端IP地址信息。这个问题是在MSDN中文论坛一个网友xiaochong4提出的,原文是:
     服务端通过getcallbackchannel可以取得回调的引用,对回调的调用肯定会有IP地址和端口的信息,有没有办法在服务端编程取得回调的endpoint信息.,查了好久资料没查到,大侠指教下。
【1】问题分析:
      WCF服务能否获取客户端地址IP信息,这个问题相信很多人都遇到过。而且很多人发愁找不到解决问题的办法。我们传统的机遇Http Post/Get的网络应用和 Web Service都提供了获取客户端地址的信息的实现机制。而到了WCF,这样一个获取客户端地址的功能实现起来却是相当复杂。早期的WCF没有提供相应的支持。
      现在Orcas也就是VS2008提供了实现机制,.NET3.5一起发布。
【2】资料收集:
【2.1】 stswordman2007年整理的一个文章 http://www.cnblogs.com/stswordman/archive/2007/05/31/699542.html。限于当时的WCF的限制,他没有找到解决办法。而且也查找了国外的论坛,老外的建议也是不可以获取客户端地址信息,WCF当时没有提供这样的特性支持。大家有兴趣可以看看WCF英文技术论坛的帖子:
1. http://social.msdn.microsoft.com/Forums/en-US/wcf/threads
   基本都是不能解决,这个受技术条件的限制,不是结论错误。现在一样做个参考。这里也对 stswordman的工作表示感谢,我后续会给出正确的代码。
【2.2】后来收集的资料, Phil Henning's WebLog: http://blogs.msdn.com/phenning/archive/2007/08/08/remoteendpointmessageproperty-in-wcf-net-3-5.aspx.这个文章,提供的解决问题的方法。
    主要使用是.NET3.5里的服务端上下文的消息实例的RemoteEndpointMessageProperty属性,获取客户端地址信息。但是限制的绑定是HTTP、TCP相关的绑定协议。网络通信的底层机制来说,数据包如果经由TCP传输,IP数据包应该包含地址和端口信息,这个我们网络编程也可以理解。但是WCF获取客户端地址信息早期却没提供相应的实现。其实按照道理来说没什么难度。只是多做个数据包的解析工作,然后把地址信息包装即可。
【3】示例代码:
    这里给出服务端获取客户端IP地址信息的示例代码分析和实现过程,这里的测试主要是针对HTTP、TCP相关的协议做了4个测试。NamePipeBinding等协议不做测试了,本地协议不需要IP和端口。我们主要测试的是几个主要的协议,来验证以上的结论。
【3.1】服务端:
    主要是对RemoteEndpointMessageProperty属性的使用来获取地址、端口信息。具体代码如下:
//1.服务契约 
        [ServiceContract(Namespace = "http://www.cnblogs.com/frank_xl/")] 
        public interface IWCFService 
        { 
                //操作契约 
                [OperationContract] 
                string SayHelloToUser(string name); 

        } 
        //2.服务类,继承接口。实现服务契约定义的操作 
        public class WCFService : IWCFService 
        { 

                //实现接口定义的方法 
                public string SayHelloToUser(string name) 
                { 
                        //提供方法执行的上下文环境 
                        OperationContext context = OperationContext.Current; 
                        //获取传进的消息属性 
                        MessageProperties properties = context.IncomingMessageProperties; 
                        //获取消息发送的远程终结点IP和端口 
                        RemoteEndpointMessageProperty endpoint = properties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty; 
                        Console.WriteLine(string.Format("Hello {0},You are    from {1}:{2}", name, endpoint.Address, endpoint.Port)); 
                        return string.Format("Hello {0},You are    from {1}:{2}", name, endpoint.Address, endpoint.Port); 


                } 
        }
【3.2】宿主:使用的是控制台托管宿主方式,延续上一个些列的特色。大家很应该很容易就上手了。简单介绍一下配置过程。    这里配置了HTPP和TCP相关的4个服务终结点进行测试:
<service behaviorConfiguration="WCFService.WCFServiceBehavior" 
                name="WCFService.WCFService"> 
                <endpoint    
                    address="http://localhost:8001/WCFService"    
                    binding="wsHttpBinding" contract="WCFService.IWCFService"> 
                </endpoint> 
                <endpoint    
                    address="net.tcp://localhost:8002/WCFService"    
                    binding="netTcpBinding" contract="WCFService.IWCFService"> 
                </endpoint> 
                <endpoint 
                    address="http://localhost:8003/WCFService" 
                    binding="basicHttpBinding" contract="WCFService.IWCFService"> 
                </endpoint> 
                <endpoint 
                    address="http://localhost:8004/WCFService" 
                    binding="wsDualHttpBinding" contract="WCFService.IWCFService"> 
                </endpoint> 
                <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> 
                <host> 
                    <baseAddresses> 
                        <add baseAddress="http://localhost:8001/"/> 
                    </baseAddresses> 
                </host> 
            </service> 
        </services>
【3.3】客户端:启动宿主和添加服务引用的过程就详细介绍了。我们分别针对每个不同的服务终结点,实例化代理进行测试。宿主会输出信息,而且客户端打印返回的消息。代码如下:
//1.WSHttpBinding_IWCFService 
                        using (WCFServiceClient wcfServiceProxyHttp = new WCFServiceClient("WSHttpBinding_IWCFService")) 
                        { 
                                string strUserName = "Frank Xu Lei WSHttpBinding "; 
                                string strMessage = ""; 
                                //通过代理调用SayHelloToUser服务 
                                strMessage =wcfServiceProxyHttp.SayHelloToUser(strUserName); 
                                Console.WriteLine(strMessage); 
                        } 
                        //2.NetTcpBinding_IWCFService 
                        using (WCFServiceClient wcfServiceProxyHttp = new WCFServiceClient("WSHttpBinding_IWCFService")) 
                        { 
                                string strUserName = "Frank Xu Lei NetTcpBinding "; 
                                string strMessage = ""; 
                                //通过代理调用SayHelloToUser服务 
                                strMessage = wcfServiceProxyHttp.SayHelloToUser(strUserName); 
                                Console.WriteLine(strMessage); 
                        } 
                        //3.BasicHttpBinding_IWCFService 
                        using (WCFServiceClient wcfServiceProxyHttp = new WCFServiceClient("WSHttpBinding_IWCFService")) 
                        { 
                                string strUserName = "Frank Xu Lei BasicHttpBinding "; 
                                string strMessage = ""; 
                                //通过代理调用SayHelloToUser服务 
                                strMessage = wcfServiceProxyHttp.SayHelloToUser(strUserName); 
                                Console.WriteLine(strMessage); 
                        } 
                        //4.WSDualHttpBinding_IWCFService, 
                        using (WCFServiceClient wcfServiceProxyHttp = new WCFServiceClient("WSHttpBinding_IWCFService")) 
                        { 
                                string strUserName = "Frank Xu Lei WSDualHttpBinding "; 
                                string strMessage = ""; 
                                //通过代理调用SayHelloToUser服务 
                                strMessage = wcfServiceProxyHttp.SayHelloToUser(strUserName); 
                                Console.WriteLine(strMessage); 
                        }
【3.4】测试结果:
    启动宿主、客户端,进行测试测试。结果如图:
【4】总结:
    1)以上测试可以看出,客户端的每次请求,服务端都可以获取响应的地址信息:IP+Port.获得以后大家可以再进行别的处理,比如系统日志LOG、安全限制等等。
    2)此特性只是对http和tcp相关的绑定器作用,其它绑定WCF没有做支持,和实际绑定的应用有关系。比如NamePipe等。
    3)双向通信,这个属性可以获取服务端的信息。
    4)这个属性没做欺骗检测,如果使用作为安全标准,要慎重考虑。
     以上就是WCF获取客户端机制的介绍和代码实现的讲解部分,大家基本实际项目开发可以考虑结合自身情况使用。 最后给出实现代码,可以直接运行,版本是VS2008 RTM.NET3.5,大家调试的时候注意版本兼容问题。下载地址如下:
/Files/frank_xl/WCFServiceGetClientAddressFrankXuLei.rar。有问题大家可以留言交流,也可以到MSDN中文论坛交流: http://social.microsoft.com/Forums/zh-CN/wcfzhchs/threads
参考文章:
2.老外的博客:Client IP addresses in Orcas:




 本文转自 frankxulei 51CTO博客,原文链接:http://blog.51cto.com/frankxulei/320452,如需转载请自行联系原作者

相关文章
|
9月前
|
前端开发
WCF更新服务引用报错的原因之一
WCF更新服务引用报错的原因之一
|
6月前
|
Windows
WCF服务端调用客户端.
WCF服务端调用客户端.
|
8月前
|
C# 数据安全/隐私保护
c#如何创建WCF服务到发布(SqlServer版已经验证)
c#如何创建WCF服务到发布(SqlServer版已经验证)
38 0
|
8月前
|
安全 数据库连接 数据库
WCF服务创建到发布(SqlServer版)
在本示例开始之前,让我们先来了解一下什么是wcf? wcf有哪些特点? wcf是一个面向服务编程的综合分层架构。该架构的项层为服务模型层。 使用户用最少的时间和精力建立自己的软件产品和外界通信的模型。它使得开发者能够建立一个跨平台的安全、可信赖、事务性的解决方案。且能与已有系统兼容写作。 简单概括就是:一组数据通信的应用程序开发接口。
57 0
Visual Studio 2022 创建 WCF服务 找不到
Visual Studio 2022 创建 WCF服务 找不到
|
C++
WCF基础教程(二)——解析iis8和iis8.5+VS2013发布wcf服务问题
WCF基础教程(二)——解析iis8和iis8.5+VS2013发布wcf服务问题
102 0
WCF基础教程(二)——解析iis8和iis8.5+VS2013发布wcf服务问题
WCF使用纯代码的方式进行服务寄宿
服务寄宿的目的是为了开启一个进程,为WCF服务提供一个运行的环境。通过为服务添加一个或者多个终结点,使之暴露给潜在的服务消费,服务消费者通过匹配的终结点对该服务进行调用,除去上面的两种寄宿方式,还可以以纯代码的方式实现服务的寄宿工作。
850 0
|
Windows
WCF服务寄宿到IIS
一.WCF简介: Windows Communication Foundation(WCF)是由微软开发的一系列支持数据通信的应用程序框架,可以翻译为Windows 通讯开发平台。整合了原有的windows通讯的 .net Remoting,WebService,Socket的机制,并融合有HTTP和FTP的相关技术。
1046 0
WCF服务自我寄宿
WCF服务的寄宿方式 WCF寄宿方式是一种非常灵活的操作,可以寄宿在各种进程之中,常见的寄宿有: IIS服务、Windows服务、Winform程序、控制台程序中进行寄宿,从而实现WCF服务的运行,为调用者方便、高效提供服务调用。
994 0
|
监控
Wcf通讯基础框架方案(三)——客户端
假设定义了一个服务契约: [ServiceContract(Namespace = "WcfExtension.Services.Interface")] public interface ITestService { [OperationContract] ...
689 0