-
simpson © (11.10.05 17:16) [0]Добрый день.
Хочу определить, что именно i-й клиент вызывает сейчас метод remoting-объекта.
Как реализовать сабж? -
Lamer@fools.ua © (11.10.05 23:32) [1]>Как реализовать сабж?
Хранить в remoting-объекте номер клиента? -
DiamondShark © (12.10.05 09:25) [2]Простите, а в обчном объекте у вас не возникает желания узнать, кто его вызывает? А почему? А почему тут возникает?
-
Курдль © (13.10.05 11:22) [3]А как активируется Remoting-объект на сервере?
-
simpson © (13.10.05 12:35) [4]Есть сервис, выполняющий роль remoting-сервера. К нему могут подключаться клиенты как с других машин сети, так и с той же, на которой он работает.
Требуется получить возможность в некоторых методах remoting-объекта определять, какой именно из клиентов этот метод вызвал. Нужен некий уникальный в пределах этого процесса (имеется ввиду сервис) идентификатор клиента.
Это необходимо для реализации следующей штуки. Есть объект-синглтон:
public class SingletoneSample : MarshalByRefObject, ISingletoneSample
{
public bool Lock()
{
// захватываем объект
// здесь нужно определить, что за клиент вызывает этот метод
}
public bool UnLock()
{
// освобождаем объект
// здесь тоже нужно определить, что за клиент вызывает этот метод
}
public void SomeAction()
{
// здесь выполняем какие-то действия
}
}
Remoting-сервер создает этот синглтон. Очередной клиент, прежде, чем вызвать метод SomeAction, вызывает Lock. В методе Lock синглтон проверяет - если он не захвачен никем, то запоминает клиента по его идентификатору и переходит в состояние "захвачен". Если он уже в этом состоянии, то он возвращает false, и клиент не имеет права в этом случае вызывать SomeAction.
Клиент, "захвативший" синглтон ранее, освобождает его с помощью UnLock.
Т. е., нечто вроде распределенной критической секции, если уместна такая аналогия.
public class ClientClass
{
void foo()
{
// получаем ссылку на синглтон через активатор
ISingletoneSample sample = ...
if (sample.Lock())
{
try
{
sample.SomeAction();
}
finally
{
sample.UnLock();
}
}
}
}
> Курдль © (13.10.05 11:22) [3]
См. комментарий с коде "получаем ссылку на синглтон через активатор". Т.е. Activator.GetObject
> Lamer@fools.ua © (11.10.05 23:32) [1]
Да я бы с радостью. Вопрос в том, где этот "номер" (точнее, идентификатор) взять? Что в качестве него использовать?
Сразу оговорюсь, есть вариант, когда клиент "регистрируется" у синглтона (т. е. вызывает метод синглтона, который генерирует уникальный ID клиента). Потом этот ID передается в качестве доп. параметра всем методам синглтона.
Но хотелось бы решение покрасивее. :)
> DiamondShark © (12.10.05 09:25) [2]
Потому что нужно организовать монопольный доступ к данным и ресурсам созданного синглтона. В случае с "обычным объектом" для этих целей используется критическая секция или любой другой объект синхронизации.
В случае с remoting все сложнее. Даже в приведенном мной примере использования синглтона нет никакой гарантии, что последовательный вызов с клиента Lock, SomeAction и UnLock будет происходит в одном и том же трэде на сервере. А между Lock и UnLock в реальной жизни методов будет, мягко говоря, очень много, да и про времени процесс обращения к синглтону будет растянут. -
Курдль © (13.10.05 12:42) [5]
> См. комментарий с коде "получаем ссылку на синглтон через
> активатор". Т.е. Activator.GetObject
1. Для таких целей удобнее применять не синглтон (из welknown objects), а клиенски-активируемый объект. Тогда он принимает от клиента какие угодно параметры и живет с ними, пока не будет принудительно прибит, или не исчерпает срок аренды.
2. Для синглтона на сервере можно получить инфу о клиенте, если передать ее в "контексте вызова" (CallContext) -
simpson © (13.10.05 12:43) [6]> Курдль © (13.10.05 12:42) [5]
1. CAO не подойдет по ряду причин.
2. Вот это просьба рассмотреть подробнее. -
Курдль © (13.10.05 12:54) [7]Для начала гляньте http://search.microsoft.com/search/results.aspx?qu=CallContext&View=ru-ru&st=b&c=4&s=5&swc=0
а я покка поищу свои наработки. Но предупреждаю, легко не будет! :) -
simpson © (13.10.05 12:57) [8]Спасибо. Буду читать.
-
Курдль © (13.10.05 13:06) [9]Класс, инкапсулирующий необходимые данные контекста вызова:
using System;
using System.Runtime.Remoting.Messaging;
namespace CommonNameSpace
{
/// <summary>
/// Summary description for CallContext.
/// </summary>
[Serializable]
public class CallContextData: ILogicalThreadAffinative
{
private int clientID;
private string login;
public CallContextData(int AclientID, string ALogin)
{
clientID = AclientID;
login = ALogin;
}
public int ClientID
{
get { return clientID; }
}
public string Login
{
get { return login; }
}
}
}
Удаленный объект:
using System;
using System.Runtime.Remoting.Messaging;
namespace CommonNameSpace
{
/// <summary>
/// Summary description for Class1.
/// </summary>
public class RemoteObject: MarshalByRefObject
{
public RemoteObject()
{
CallContextData ccd = (CallContextData)CallContext.GetData("CLIENT PARAMS");
if (ccd != null)
System.Console.WriteLine(String.Format("{0}\tСоздан удаленный объект с контекстом:\t{1}", DateTime.Now, ccd.Login));
else
System.Console.WriteLine(String.Format("{0}\tСоздан удаленный объект", DateTime.Now));
}
public string CheckCallContext()
{
CallContextData ccd = (CallContextData)CallContext.GetData("CLIENT PARAMS");
System.Console.WriteLine(String.Format("{0}\tКонтекст вызова = \t{1}", DateTime.Now, ccd.Login));
return ccd.Login;
}
}
}
Серверная консоль:
using System;
using System.Runtime.Remoting.Messaging;
namespace CommonNameSpace
{
/// <summary>
/// Summary description for Class1.
/// </summary>
public class RemoteObject: MarshalByRefObject
{
public RemoteObject()
{
CallContextData ccd = (CallContextData)CallContext.GetData("CLIENT PARAMS");
if (ccd != null)
System.Console.WriteLine(String.Format("{0}\tСоздан удаленный объект с контекстом:\t{1}", DateTime.Now, ccd.Login));
else
System.Console.WriteLine(String.Format("{0}\tСоздан удаленный объект", DateTime.Now));
}
public string CheckCallContext()
{
CallContextData ccd = (CallContextData)CallContext.GetData("CLIENT PARAMS");
System.Console.WriteLine(String.Format("{0}\tКонтекст вызова = \t{1}", DateTime.Now, ccd.Login));
return ccd.Login;
}
}
} -
Курдль © (13.10.05 13:08) [10]Скосячил, вот истинная серверная консоль:
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
namespace CommonNameSpace
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
TcpChannel channel = new TcpChannel(8008);
ChannelServices.RegisterChannel(channel);
System.Console.WriteLine(String.Format("{0}\tСоздан и зарегистрирован канал", DateTime.Now));
RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemoteObject), "roURI", WellKnownObjectMode.SingleCall);
System.Console.WriteLine("Press ENTER to exit");
System.Console.ReadLine();
}
}
} -
DiamondShark © (13.10.05 14:20) [11]
> Клиент, "захвативший" синглтон ранее, освобождает его с
> помощью UnLock.
> Т. е., нечто вроде распределенной критической секции, если
> уместна такая аналогия.
Уй, как замечательно.
Вот я вызвал Lock, а потом у меня сетка рухнула.
И что станет с сервером?
Синглетон должен быть stateless.
> В случае с "обычным объектом" для этих целей используется
> критическая секция или любой другой объект синхронизации.
Ну и сделайте client-activated объект. Пусть уже он пользуется стандартными механизмами синхронизации. -
simpson © (13.10.05 14:59) [12]> Ну и сделайте client-activated объект
См. simpson © (13.10.05 12:43) [6]
> Вот я вызвал Lock, а потом у меня сетка рухнула.
Это можно предусмотреть.
> Синглетон должен быть stateless
Не согласен. -
DiamondShark © (13.10.05 19:09) [13]
> > Ну и сделайте client-activated объект
> См. simpson © (13.10.05 12:43) [6]
Тема не раскрыта.
> > Вот я вызвал Lock, а потом у меня сетка рухнула.
> Это можно предусмотреть.
Каким образом? Городить велосипед?
А упавший cao подберёт life-time service.
> > Синглетон должен быть stateless
> Не согласен.
Удачи. -
newbusin (29.07.07 00:12) [14]Добрый день
Мне очень нравится ваш форум,
не мог бы кто нибудь разьеснить последнее обсуждение,
очень увлекательная тема)
Заранее Спосибо