пятница, 18 июля 2008 г.

Взаимодействие процессов по IpcChannel

Недавно столкнулся с необходимостью организовать взаимодействие двух .NET процессов в рамках одного компьютера. Немного покумекав, решил для этих целей воспользоваться «родной» для платформы .NET технологией – Remoting. Первоначально в качестве канала для «общения» процессов планировал выбрать протокол TCP (TcpChannel), но затем обнаружил что во втором фреймворке появился новый канал ремоутинга, который идеально подходит для мой задачи – IpcChannel. Этот канал использует в своей работе именованные каналы (named pipes) и был разработан специально для организации взаимодействия нескольких процессов в рамках одного компьютера и согласно MSDN, работает намного быстрее TCP и HTTP. Использование технологии Remoting крайне просто и ниже я привел пример сервера и клиента взаимодействующих по каналу IpcChannel.
Ниже приведен код для сервера.
class ServerHost
{
static void Main( string[] args )
{
IDictionary settings = new Hashtable();
settings["portName"] = "IPC_Test";
settings["exclusiveAddressUse"] = false;

IChannel channel = new IpcChannel(settings, null, null);
ChannelServices.RegisterChannel(channel, false);
RemotingConfiguration.RegisterWellKnownServiceType(
typeof( GreetingService ),
"GreetingService",
WellKnownObjectMode.Singleton );

Console.WriteLine("Server started. Press ENTER to shutdown.");
Console.ReadLine();
ChannelServices.UnregisterChannel( channel );
}
}

Далее идет код для клиента этого сервера
class ClientApp
{
static void Main( string[] args )
{
IGreetingService service = (IGreetingService)Activator.GetObject(
typeof( IGreetingService ),
"ipc://IPC_Test/GreetingService" );

Console.WriteLine(service.GetGreeting("IPC Tester"));
Console.ReadLine();
}
}

И наконец, пример интерфейса и реализация сервиса, который используемых как клиентом, так и сервером.
public interface IGreetingService
{
string GetGreeting(string userName);
}

class GreetingService: MarshalByRefObject, IGreetingService
{
public string GetGreeting( string userName )
{
return "Hello, " + userName;
}
}
Обратите внимание на установку параметра exclusiveAddressUse в false. В MSDN есть предупреждение, что установка его в false позволит нескольким серверам использовать одни и тот же порт, что может привести к брешам в безопасности такой архитектуры, однако если его не установить в false используемый сервером порт может быть недоступным еще около 1 секунды после завершения работы сервера.
Ниже приведен еще один пример реализации хоста сервера, но настройка ремоутинга произведена посредством конфигурационного файла.
class ConfigServerHost
{
static void Main( string[] args )
{
RemotingConfiguration.Configure( "ConfigServerHost.exe.config", false );

Console.WriteLine( "Server started. Press ENTER to shutdown" );
Console.ReadLine();
}
}

И наконец, app.config, который после компиляции проекта преврацается в ConfigServerHost.exe.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application name="IPC Sample">
<service>
<wellknown mode="Singleton" type="ServerHost.GreetingService, ServerHost" objectUri="GreetingService" />
</service>

<channels>
<channel ref="ipc" portName="IPC_Test" exclusiveAddressUse="false" />
</channels>
</application>
</system.runtime.remoting>
</configuration>

Комментариев нет: