Remoting獲取客戶端外網IP

     領導又有了新的要求,在用戶登錄的時候記錄用戶的IP地址和機器名。

     在C#中,獲取本機的機器名和IP地址,甚至網卡的MAC地址,都是很簡單的事情,有封裝好的類和方法可以使用,但現在遇到的問題是,如果客戶端的機器是在另一個局域網內,那網卡的IP地址是局域網地址,這對我們來說沒有用,這就要記錄外網的IP,但是Remoting沒有現成的方法來獲取客戶端的IP,google了一下,網上比較多的是采用在Server端注冊自定義Server Channel Sink,通過Transport Headers來獲取Request的IP。于是我就用了別人寫好的現成的Sink,以及學習了Rickie的一篇《如何定制Sink擴展.Net Remoting功能》。
     Rickie的文章:http://www.cnblogs.com/rickie/archive/2004/10/21/54891.html
     自定義的Sink的類:http://blog.joycode.com/tingwang/articles/39610.aspx

 

 

public   class  ClientIPServerSinkProvider : IServerChannelSinkProvider
    
{
        
private IServerChannelSinkProvider next = null;

        
public ClientIPServerSinkProvider()
        
{
        }


        
public ClientIPServerSinkProvider(IDictionary properties, ICollection providerData)
        
{
        }


        
public void GetChannelData(IChannelDataStore channelData)
        
{
        }


        
public IServerChannelSink CreateSink(IChannelReceiver channel)
        
{
            IServerChannelSink nextSink 
= null;
            
if (next != null)
            
{
                nextSink 
= next.CreateSink(channel);
            }


            
return new ClientIPServerSink(nextSink);
        }


        
public IServerChannelSinkProvider Next
        
{
            
get return next; }
            
set { next = value; }
        }

    }


    
public   class  ClientIPServerSink : BaseChannelObjectWithProperties, IServerChannelSink, IChannelSinkBase
    
{

        
private IServerChannelSink _next;

        
public ClientIPServerSink(IServerChannelSink next)
        
{
            _next 
= next;
        }


        
public void AsyncProcessResponse(IServerResponseChannelSinkStack sinkStack, Object state, IMessage msg, ITransportHeaders headers, Stream stream)
        
{
        }


        
public Stream GetResponseStream(IServerResponseChannelSinkStack sinkStack, Object state, IMessage msg, ITransportHeaders headers)
        
{
            
return null;
        }


        
public System.Runtime.Remoting.Channels.ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream)
        
{
            
if (_next != null)
            
{
                IPAddress ip 
= requestHeaders[CommonTransportKeys.IPAddress] as IPAddress;
                Console.WriteLine(ip.ToString());
                CallContext.SetData(
"ClientIPAddress", ip);
                ServerProcessing spres 
= _next.ProcessMessage(sinkStack, requestMsg, requestHeaders, requestStream, out responseMsg, out responseHeaders, out responseStream);

                
return spres;
            }

            
else
            
{
                responseMsg 
= null;
                responseHeaders 
= null;
                responseStream 
= null;

                
return new ServerProcessing();
            }

        }


        
public IServerChannelSink NextChannelSink
        
{
            
get return _next; }
            
set { _next = value; }
        }

    }

 

     在Remoting的服務端加入了這個類后,由于我是在IIS上承載的Remoting,所以就需要修改Web.config文件來啟用這個Sink。

 

 

       < channels >
        
< channel port = " 8000 "   ref = " http "  name  = " httpServer " >
          
< serverProviders >
            
< formatter  ref = " soap "  typeFilterLevel = " Full " />
            
< formatter  ref = " binary "  typeFilterLevel = " Full " />
            
< provider type = " Galaxy.Server.Remoting.ClientIPServerSinkProvider, Galaxy.Server.Remoting "   />
          
</ serverProviders >
        
</ channel >
        
< channel port = " 9000 "   ref = " tcp "  name  = " tcpServer " >
          
< serverProviders >
            
< formatter  ref = " soap "  typeFilterLevel = " Full " />
            
< formatter  ref = " binary "  typeFilterLevel = " Full " />
            
< provider type = " Galaxy.Server.Remoting.ClientIPServerSinkProvider, Galaxy.Server.Remoting "   />
          
</ serverProviders >
        
</ channel >
      
</ channels >

 

     做完這個后,以后只需在服務器端通過 ((System.Net.IPAddress)System.Runtime.Remoting.Messaging.CallContext.GetData("ClientIPAddress")).ToString() 就可以獲取Request的IP了。

你可能感兴趣的:(IP)