Идентификация клиента во время вызова удаленного взаимодействия.NET
Учитывая этот класс MarshalByRef:
public class MyRemotedClass : MarshalByRef
{
public void DoThis()
{
...
}
public void DoThat()
{
...
}
}
Код на стороне клиента:
MyRemotedClass m = GetSomehowMyRemotedClass();
m.DoThis();
m.DoThat();
У меня может быть несколько клиентов, делающих одно и то же одновременно. Я хотел бы выделить клиентов. Как я могу определить внутри методов удаленного доступа, с помощью которых выполняется удаленный вызов? Например, я мог бы войти, кто что сделал. (На самом деле мне не нужно отслеживать истинную информацию о клиенте, я просто хочу иметь возможность группировать вызовы по клиентам.)
[Отредактировано для добавления дополнительной информации]
У меня есть огромное количество кода для покрытия, включая свойства. Поэтому расширение списка входных параметров не вариант.
1 ответ
Одна из вещей, которую вы можете сделать, - это идентифицировать клиента по IP-адресу, внедрив IServerChannelSinkProvider
,
Добавьте этот класс в ваш удаленный хост-проект:
ClientIPServerSinkProvider.cs
using System;
using System.Collections;
using System.IO;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Channels;
using System.Threading;
using System.Net;
namespace MyRemotingEnvironment
{
public class ClientIPServerSinkProvider :
IServerChannelSinkProvider
{
private IServerChannelSinkProvider _nextProvider = null;
public ClientIPServerSinkProvider()
{
}
public ClientIPServerSinkProvider(
IDictionary properties,
ICollection providerData)
{
}
public IServerChannelSinkProvider Next
{
get { return _nextProvider; }
set { _nextProvider = value; }
}
public IServerChannelSink CreateSink(IChannelReceiver channel)
{
IServerChannelSink nextSink = null;
if (_nextProvider != null)
{
nextSink = _nextProvider.CreateSink(channel);
}
return new ClientIPServerSink(nextSink);
}
public void GetChannelData(IChannelDataStore channelData)
{
}
}
public class ClientIPServerSink :
BaseChannelObjectWithProperties,
IServerChannelSink,
IChannelSinkBase
{
private IServerChannelSink _nextSink;
public ClientIPServerSink(IServerChannelSink next)
{
_nextSink = next;
}
public IServerChannelSink NextChannelSink
{
get { return _nextSink; }
set { _nextSink = value; }
}
public void AsyncProcessResponse(
IServerResponseChannelSinkStack sinkStack,
Object state,
IMessage message,
ITransportHeaders headers,
Stream stream)
{
IPAddress ip = headers[CommonTransportKeys.IPAddress] as IPAddress;
CallContext.SetData("ClientIPAddress", ip);
sinkStack.AsyncProcessResponse(message, headers, stream);
}
public Stream GetResponseStream(
IServerResponseChannelSinkStack sinkStack,
Object state,
IMessage message,
ITransportHeaders headers)
{
return null;
}
public ServerProcessing ProcessMessage(
IServerChannelSinkStack sinkStack,
IMessage requestMsg,
ITransportHeaders requestHeaders,
Stream requestStream,
out IMessage responseMsg,
out ITransportHeaders responseHeaders,
out Stream responseStream)
{
if (_nextSink != null)
{
IPAddress ip =
requestHeaders[CommonTransportKeys.IPAddress] as IPAddress;
CallContext.SetData("ClientIPAddress", ip);
ServerProcessing spres = _nextSink.ProcessMessage(
sinkStack,
requestMsg,
requestHeaders,
requestStream,
out responseMsg,
out responseHeaders,
out responseStream);
return spres;
}
else
{
responseMsg = null;
responseHeaders = null;
responseStream = null;
return new ServerProcessing();
}
}
}
}
Затем, когда вы запускаете удаленный хост, сделайте что-то вроде следующего:
BinaryServerFormatterSinkProvider bp = new BinaryServerFormatterSinkProvider();
ClientIPServerSinkProvider csp = new ClientIPServerSinkProvider();
csp.Next = bp;
Hashtable ht = new Hashtable();
ht.Add("port", "1234"); // Your remoting port number
TcpChannel channel = new TcpChannel(ht, null, csp);
ChannelServices.RegisterChannel(channel, false);
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(MyRemotedClass),
"MyRemotedClass.rem",
WellKnownObjectMode.SingleCall);
В вызовах вашего метода вы можете получить доступ к IP-адресу клиента, выполнив:
public class MyRemotedClass : MarshalByref
{
public void DoThis()
{
string clientIP = CallContext.GetData("ClientIPAddress").ToString();
}
}