其实在服务端Remoting可以像读取一个变量一样来获取到连接过来的客户端的IP,不过这个IP不是太容易的取到。
网上有一个解决方案就是使用配置文件来吸取IP地址,但是这个方案需要我们使用配置文件来使用Remoting,如果我们是代码形式的程序,那么怎样获取客户端IP呢。
Remoting、WebService底层都是用Socket来实现,Socket本身很容易的可以获取到IP地址,所以理论上Remoting获取客户端IP是通过的。
我们可以从吸取器入手来获取,假如我们使用TCP通道来通信,在服务端使用TcpServerChannel类,该类其实已支持了吸取器,构造函数如下:
public TcpServerChannel(string name, int port, IServerChannelSinkProvider sinkProvider);
TcpServerChannel类默认的吸取器是BinaryServerFormatterSinkProvider,而吸取器可以设置链表上的下一个吸取器,然后依次执行每一个吸取器。
我们可以得到如下的代码:
IServerChannelSinkProvider serverSink = new ClientIPServerSinkProvider();
BinaryServerFormatterSinkProvider firstSink = new BinaryServerFormatterSinkProvider();
firstSink.Next = serverSink;
TcpServerChannel channel = new TcpServerChannel("tcpserver", port, firstSink);
ChannelServices.RegisterChannel(channel, true);
RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemotableClass), "RemotableClass", WellKnownObjectMode.Singleton);
到这里,如果定义好了RemotableClass类,那么就可以直接取IP地址了:
public class RemotableClass : MarshalByRefObject
{
protected string getIPAddress()
{
System.Net.IPAddress ip = System.Runtime.Remoting.Messaging.CallContext.GetData("ClientIPAddress") as System.Net.IPAddress;
if (ip != null)
{
return ip.ToString();
}
return null;
}
}
如果不知道吸取器的代码,可以参考如下:
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;
CallContext.SetData("ClientIPAddress", ip);
return _next.ProcessMessage(sinkStack, requestMsg, requestHeaders, requestStream, out responseMsg, out responseHeaders, out responseStream);
}
else
{
responseMsg = null;
responseHeaders = null;
responseStream = null;
return ServerProcessing.Complete;
}
}
public IServerChannelSink NextChannelSink
{
get
{
return _next;
}
set
{
_next = value;
}
}
}
到这里就完成了。