first, create your own ServerChannelSink class and ServerChannelSinkProvider classusing System; using System.Runtime.Remoting.Channels; using System.Net; using System.Runtime.Remoting.Messaging; using System.Collections; using System.IO;public class CClientIPInjectorSink : BaseChannelObjectWithProperties,IServerChannelSink { private IServerChannelSink _nextSink;
public CClientIPInjectorSink(IServerChannelSink nextSink) { _nextSink = nextSink; }
public void AsyncProcessResponse(IServerResponseChannelSinkStack sinkStack, object state, IMessage msg, ITransportHeaders headers, Stream stream) { //get the client's ip address, and put it in the call context. //This value will be extracted later so we can determine the actual //address of the client. try { IPAddress IPAddr = (IPAddress)headers[CommonTransportKeys.IPAddress]; CallContext.SetData("ClientIP", IPAddr); } catch{} //forward to stack for further processing sinkStack.AsyncProcessResponse(msg, headers,stream); } public Stream GetResponseStream(IServerResponseChannelSinkStack sinkStack, object state, IMessage msg, ITransportHeaders headers) { return null; } public IServerChannelSink NextChannelSink { get { return _nextSink; } } public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream) { //get the client's ip address, and put it in the call context. //This value will be extracted later so we can determine the actual //address of the client. try { IPAddress IPAddr = (IPAddress)requestHeader[CommonTransportKeys.IPAddress]; CallContext.SetData("ClientIP", IPAddr); } catch{} //pushing onto stack and forwarding the call sinkStack.Push(this,null); ServerProcessing srvProc = _nextSink.ProcessMessage(sinkStack,requestMsg, requestHeaders, requestStream, out responseMsg,out responseHeaders, out responseStream); if(srvProc == ServerProcessing.Complete) { //TODO - implement post processing } return srvProc; } }//this class is used as the sink provider that creates the //CClientiPInjectorSink. It is used by the channel //so that we can get the caller's ip address public class CClientIPInjectorSinkProvider : IServerChannelSinkProvider { private IServerChannelSinkProvider _nextProvider; public CClientIPInjectorSinkProvider(){} public CClientIPInjectorSinkProvider(IDictionary properties, ICollection providerdata){} public IServerChannelSink CreateSink(IChannelReceiver channel) { //create other sinks in the chain IServerChannelSink nextSink = _nextProvider.CreateSink(channel); return new CClientIPInjectorSink(nextSink); } public void GetChannelData(IChannelDataStore channelData) { //not needed } public IServerChannelSinkProvider Next { get { return _nextProvider; } set { _nextProvider = value; } } }
then use it to declare your channel//this part is done where you declare your channelHashtable props; props.Add("port", 10000);//create the binary server formatter sink BinaryServerFormatterSinkProvider BinProvider = new BinaryServerFormatterSinkProvider(); BinProvider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;//Create the ip injector sink CClientIPInjectorSinkProvider IpInjProvider = new CClientIPInjectorSinkProvider();//link the providers BinProvider.Next = IpInjProvider;System.Runtime.Remoting.Channels.Tcp.TcpChannel _PublicChannel = new System.Runtime.Remoting.Channels.Tcp.TcpChannel(props, Nothing,BinProvider); _PublicChannel.StartListening(null);
sorry, forgot one thing. the way to get the IP back:IPAddress clientIP = (IPAddress)CallContext.GetData("ClientIP");
using System.Runtime.Remoting.Channels;
using System.Net;
using System.Runtime.Remoting.Messaging;
using System.Collections;
using System.IO;public class CClientIPInjectorSink : BaseChannelObjectWithProperties,IServerChannelSink
{
private IServerChannelSink _nextSink;
public CClientIPInjectorSink(IServerChannelSink nextSink)
{
_nextSink = nextSink;
}
public void AsyncProcessResponse(IServerResponseChannelSinkStack sinkStack,
object state,
IMessage msg,
ITransportHeaders headers,
Stream stream)
{
//get the client's ip address, and put it in the call context.
//This value will be extracted later so we can determine the actual
//address of the client.
try
{
IPAddress IPAddr = (IPAddress)headers[CommonTransportKeys.IPAddress];
CallContext.SetData("ClientIP", IPAddr);
}
catch{} //forward to stack for further processing
sinkStack.AsyncProcessResponse(msg, headers,stream);
} public Stream GetResponseStream(IServerResponseChannelSinkStack sinkStack,
object state,
IMessage msg,
ITransportHeaders headers)
{
return null;
} public IServerChannelSink NextChannelSink
{
get
{
return _nextSink;
}
} public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack,
IMessage requestMsg,
ITransportHeaders requestHeaders,
Stream requestStream,
out IMessage responseMsg,
out ITransportHeaders responseHeaders,
out Stream responseStream)
{
//get the client's ip address, and put it in the call context.
//This value will be extracted later so we can determine the actual
//address of the client.
try
{
IPAddress IPAddr = (IPAddress)requestHeader[CommonTransportKeys.IPAddress];
CallContext.SetData("ClientIP", IPAddr);
}
catch{} //pushing onto stack and forwarding the call
sinkStack.Push(this,null); ServerProcessing srvProc =
_nextSink.ProcessMessage(sinkStack,requestMsg,
requestHeaders, requestStream,
out responseMsg,out responseHeaders,
out responseStream);
if(srvProc == ServerProcessing.Complete)
{
//TODO - implement post processing
}
return srvProc;
}
}//this class is used as the sink provider that creates the
//CClientiPInjectorSink. It is used by the channel
//so that we can get the caller's ip address
public class CClientIPInjectorSinkProvider : IServerChannelSinkProvider
{ private IServerChannelSinkProvider _nextProvider; public CClientIPInjectorSinkProvider(){} public CClientIPInjectorSinkProvider(IDictionary properties,
ICollection providerdata){} public IServerChannelSink CreateSink(IChannelReceiver channel)
{
//create other sinks in the chain
IServerChannelSink nextSink = _nextProvider.CreateSink(channel);
return new CClientIPInjectorSink(nextSink);
}
public void GetChannelData(IChannelDataStore channelData)
{
//not needed
} public IServerChannelSinkProvider Next
{
get
{
return _nextProvider;
}
set
{
_nextProvider = value;
}
}
}
props.Add("port", 10000);//create the binary server formatter sink
BinaryServerFormatterSinkProvider BinProvider = new BinaryServerFormatterSinkProvider();
BinProvider.TypeFilterLevel =
System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;//Create the ip injector sink
CClientIPInjectorSinkProvider IpInjProvider = new CClientIPInjectorSinkProvider();//link the providers
BinProvider.Next = IpInjProvider;System.Runtime.Remoting.Channels.Tcp.TcpChannel _PublicChannel
= new System.Runtime.Remoting.Channels.Tcp.TcpChannel(props, Nothing,BinProvider);
_PublicChannel.StartListening(null);
TO:ermachao() ,客户端挺难获取动态的IP哦。