其实在服务端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; } } }
到这里就完成了。