Віталій Білієнко, МП-1

•	   Веб сервіси (в т.ч. Web Services Enhancements та Windows Communication Foundation)

•	   Технологія .NET Remoting

Основна ідея – звертатися до інших об'єктів .NET однаково, незалежно від того, в якому процесі чи на якій машині вони знаходяться.

При цьому від розробника приховуються всі низькорівневі деталі цього процесу.

System.Runtime.Remoting – найважливіші об'єкти (RemotingConfiguration, RemotingException, RemotingServices, ObjRef)

System.Runtime.Remoting.Channels – класи для роботи з різними каналами зв'язку

System.Runtime.Remoting.Messaging – підтримка передачі повідомлень (в т.ч. асинхронно)

System.Runtime.Remoting.Contexts – робота з контекстами об'єктів (середовищем)

•	Створити об'єкт, до якого будемо звертатися віддалено
•	Створити і налаштувати серверне застосування, що буде містити наш об'єкт і надавати послуги звертання до нього
•	Створити і налаштувати клієнтське застосування, що буде звертатися до нашого об'єкта

Об'єкт, доступатися до якого можна віддалено, повинен передаватися через межі контексту за посиланням:
public class Multiplier : MarshalByRefObject 
От і все щодо об'єкта

Якщо віддаленому об'єкту будуть передаватися в якості параметрів інші об'єкти, вони повинні бути здатними до приведення в послідовну форму:
[Serializable]
public class Matrix

Варіанти активації об'єктів (WellKnownObjectMode):
•	Single call – об'єкт не зберігає стан між запитами (знищується після кожного і створюється, коли потрібно)
•	Singleton – створюється один раз і обслуговує клієнтів, зберігаючи стан (до явного знищення)
•	Client-activated – активуються внаслідок запиту клієнта. Застосовується спеціальне керування життєвим циклом для уникнення “витоку” ресурсів

Варіанти серверного застосування:
•	Консольна програма – просте і зручне рішення для початкової розробки
•	Windows-програма – якщо потрібен потужний інтерфейс користувача
•	Програма ASP.NET – виконання в контексті IIS, доступ до потужних засобів кешування, сесій, засобів безпеки (SSL); можлива навіть обгортка для об'єкта у вигляді веб сервісу
•	Служба Windows – автоматичний запуск і зручний контроль за активністю

Варіанти форматування запитів:
•	Бінарне (IBinaryFormatter) – об'єкти серіалізуються в двійкове представлення (ефективність і об'єм даних)
•	SOAP (SoapFormatter) – обєкти серіалізуються в XML-формат Simple Object Access Protocol

Варіанти каналів зв'язку:
•	TCP – за замовчуванням форматування бінарне (найшвидша доступна комбінація)
•	HTTP – за замовчуванням форматування SOAP. Зручний для глобальних мереж
•	IPC – InterProcess Communication – спеціально для звертання до об'єктів на тій же машині (найшвидший, оминає мережні протоколи). Цей канал з'явився тільки в .NET Framework 2.0

Хостінг об'єкта – програмна конфігурація

using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
…………………….
// Створюємо і реєструємо канал
IChannel tcpChannel = new TcpChannel(8005);
ChannelServices.RegisterChannel(tcpChannel, false);

// Реєструємо об'єкт           RemotingConfiguration.RegisterWellKnownServiceType(typeof(Multiplier), "Multiplier.rem", WellKnownObjectMode.Singleton);

Хостінг об'єкта – декларативна конфігурація (App.config)
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.runtime.remoting>
    <application>
      <service>
        <wellknown
           mode="Singleton"
           type="Multiplier, MyRemoting"
           objectUri="Multiplier.rem"
            />
      </service>
      <channels>
        <channel ref="tcp" port="8005"/>
      </channels>
    </application>
  </system.runtime.remoting>
</configuration>

Клієнт – програмна конфігурація

using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

// Створюємо і реєструємо канал
TcpClientChannel channel = new TcpClientChannel();
ChannelServices.RegisterChannel(channel, false);

// Реєструємо об'єкт RemotingConfiguration.RegisterWellKnownClientType(typeof(Multiplier), "tcp://localhost:8005/Multiplier.rem");

Клієнт – декларативна конфігурація (App.config)
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.runtime.remoting>
    <application>
      <client>
        <wellknown
           type="Multiplier, MyRemoting"
           url="tcp://localhost:8005/Multiplier.rem"
            />
      </client>
      <channels>
        <channel ref="tcp" />
      </channels>
    </application>
  </system.runtime.remoting>
</configuration>

namespace MyRemoting
{
    public class Multiplier : MarshalByRefObject
    {
        public int[,] Multiply(int[,] A, int[,] B, int start, int num)
        {
            ……………
        }
    }
}

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.runtime.remoting>
    <application>
      <service>
        <wellknown
           mode="Singleton"
           type="MyRemoting.Multiplier, MyRemoting"
           objectUri="Multiplier.rem"
            />
      </service>
      <channels>
        <channel ref="tcp" port="8989"/> <!-- на іншому сервері порт 8990 -->
      </channels>
    </application>
  </system.runtime.remoting>
</configuration>

using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

namespace RemHost
{
    class Program
    {
        static void Main(string[] args)
        {
            RemotingConfiguration.Configure("RemHost.exe.config", false);

            Console.WriteLine("Server started!\r\nPress Enter to stop.");
            Console.ReadLine();
        }
    }
}

using System.Runtime.Remoting;
using MyRemoting;

class Program
{
    public delegate int[,] RunDelegate(int[,] A, int[,] B, int start, int num);

    const int size = 1000;
    static HiPerfTimer timer = new HiPerfTimer();
    static RunDelegate d1, d2;
    static IAsyncResult r1, r2;
    static bool comp1 = false, comp2 = false;

    static int[,] A = new int[size, size];
    static int[,] B = new int[size, size];

Multiplier ob1 = Activator.GetObject(typeof(Multiplier), "tcp://localhost:8989/Multiplier.rem") as Multiplier;
Multiplier ob2 = Activator.GetObject(typeof(Multiplier), "tcp://localhost:8990/Multiplier.rem") as Multiplier;

d1 = new RunDelegate(ob1.Multiply);
d2 = new RunDelegate(ob2.Multiply);

AsyncCallback c1 = new AsyncCallback(TopPartCompleted);
AsyncCallback c2 = new AsyncCallback(BottomPartCompleted);

r1 = d1.BeginInvoke(A, B, 0, size / 2, c1, null);
r2 = d2.BeginInvoke(A, B, size / 2, size, c2, null);

Console.WriteLine("still alive...");
Console.ReadLine();

static void TopPartCompleted(IAsyncResult result)
{
    int[,] C1 = d1.EndInvoke(result);
}

static void BottomPartCompleted(IAsyncResult result)
{
    int[,] C2 = d2.EndInvoke(result);
}

.NET Remoting надає можливість розширення за рахунок побудови розробником власних класів – нових форматувальників, нових каналів зв’язку, проксі і т.п.

•	   Sara Morgan, Bill Ryan, Shannon Horn, Mark Blomsma – “Microsoft .NET Framework 2.0. Distributed Application Development”, Microsoft Press, 2007
•	   Ingo Rammer - “Advanced .NET Remoting”, Apress, 2002
•	   .NET Remoting Overview (для початку) (http://msdn2.microsoft.com/en-us/library/kwdt6w2k.aspx)