Remoting-программирование
Программирование в сетях можно вести в нескольких пространствах имен - System.NET.Sokets, System.Messaging, System.Runtime.Remoting. На этой страничке я расскажу о программировании в последнем пространстве - ибо при написании первой проги - я cтолкнулся с таким количеством глюков, что понял что в следующей своей проге (или кому-то другому) лучше сразу начинать с работающего проекта.
В Remoting некий класс можно сделать доступным через сеть. Для начала надо описать интерфейсы этого класса:
00001: Public Interface IRemoteObject 00002: Function GetSum(ByVal X As Double) As Double 00003: Function GetLocation() As String 00004: End Interface
Для чего это надо делать. Дело в том, что в классической технологии Remoting надо копию этого серверного класса отдавать клиенту и устанавливать на него ссылку. Как я не старался - после установления ссылки это серверный класс просто прилинковывался статически и никакого удаленного вызова просто не происходило. Поэтому на клиенте я прилинковываю ТОЛЬКО интерфейс этого серверного класса - физическое отсутствие на клиенте самого класса гарантирует от ошибки когда никакого удаленного вызова нет и в помине.
Теперь собственно сам класс, который можно будет вызывать через сеть. Он в технологии Remoting является серверным классом (хотя как раз-то расположен он обычно на клиенте в классическом понимании этого слова) - этот класс только выполняет требования клиента и никогда не создает действий по своей инициативе. Хотя иногда может - когда он генерит события - но это более сложный вариант...
Для простейшего проекта текст этого класса-исполнителя будет таким:
00001: Public Class RemoteObject 00002: Inherits MarshalByRefObject 00003: Implements RemoteObjectInterfaces.IRemoteObject 00004: 00005: Public Function Calc(ByVal X As Double) As Double _ 00006: Implements RemoteObjectInterfaces.IRemoteObject.GetSum 00007: Calc = X * X 00008: Console.WriteLine("Получено - " & X.ToString) 00009: End Function 00010: 00011: ' This method allows you to verify that Remoting is working. 00012: Public Function GetLocation() As String _ 00013: Implements RemoteObjectInterfaces.IRemoteObject.GetLocation 00014: Return AppDomain.CurrentDomain.FriendlyName 00015: End Function 00016: 00017: End Class
Обратите внимание, что в этом проекте тоже нужна ссылка на описание интерфесов - тк этот класс реализует интерфейсы, которые мы отдали на клиентскую машину. На этой машине тоже должна быть копия описания интерфейсов.
Также обратите внимание на строку 14 - эта замечательная находка (не моя) позволяет определить на какой именно машине этот класс сейчас исполняется. У клиента должно получатся имя приложения, выполняемого на сервере.
Следующая фишка технологии Remoting - этот класс (доступный удаленно ) должен где-то хостится, т.е. на неком аналоге Web-сервера, иначе говоря нужен класс поддерживающий соединение с сетью и загружающий при вызовах экземпляр вышеописанного класса. Этот класс делают часто в виде службы. Он должен висеть на указанном порту и слушать сеть. Если никто сеть не слушает - то никакого взаимодействия по Remoting не будет. Для простейшего варианта этот класс может быть таким:
00001: Imports System.Runtime.Remoting 00002: 00003: Module Module1 00004: 00005: Dim Channels() As System.Runtime.Remoting.Channels.IChannel 00006: Dim Channel As Object 00007: Dim Config As System.Runtime.Remoting.WellKnownServiceTypeEntry 00008: 00009: Sub Main() 00010: Try 00011: RemotingConfiguration.Configure("..\App1.config") 00012: Catch x As SystemException 00013: MsgBox("Ошибка загрузки конфигурации сервера .Remoting " & vbCrLf & x.Message) 00014: End Try 00015: 00016: Console.WriteLine("Сервер NET.REMOTING Started at : " & Now & vbCrLf) 00017: Config = RemotingConfiguration.GetRegisteredWellKnownServiceTypes(0) 00018: Channels = System.Runtime.Remoting.Channels.ChannelServices.RegisteredChannels 00019: For Each Channel In Channels 00020: Console.WriteLine("Канал (Channel) : " & Channel.channeldata.channeluris(0) & vbCrLf) 00021: Next 00022: Console.WriteLine(vbCrLf & _ 00023: "Имя REMOTING-сервиса - ObjectUri : " & Config.ObjectUri & vbCrLf & _ 00024: "Режим (SingleTon/SingleCall) Mode : " & Config.Mode & vbCrLf & _ 00025: "Удаленно доступный класс - ObjectType : " & Config.ObjectType.FullName.ToString & vbCrLf & _ 00026: "Удаленно будет вызвана сборка : " & Config.ObjectType.Assembly.Location & vbCrLf) 00027: 00028: Console.WriteLine("Enter - Закрыть сервер ...") 00029: Console.ReadLine() 00030: End Sub 00031: 00032: End Module
Этот класс интересен тем, что все настройки сети вынесены во внешний XML-файл, который студия стандартно добавляет как файл конфигурации проекта. В этом файле всегда можно поменять порт, на котором класс-хостинг слушает клиентские запросы и вид Remoting-взаимодействия TCP или HTTP.
В принципе есть полное описание всех тегов конфигурации Remoting - которое можно посмотреть здесь. В этом файле важно правильно задать имена классов и сборки в параметре Type и имя Remoring-сервиса в параметре objectUri. Mode - это срок жизни серверного класса - которое определяет наш класс-хостер. Такое как указано выше - озачает загрузку классом-хостером каждого экземпляра серверного класса на каждый запрос. Sigleton - означает загрузку одного класса для всех клиентских запросов. RemoteObjects - означает здесь имя сборки (DLL-файла), RemoteObject - имя серверного класса в этой сборке.
Следующий этап - это изготовление клиента, который будет отсылать серверу запросы. Допустим это будет вот такая форма и вот такой текст:
00001: Imports System.Runtime.Remoting 00002: Imports System.Runtime.Remoting.Lifetime 00003: 00004: Public Class ClientForm 00005: Inherits System.Windows.Forms.Form 00006: 00007: #Region " Windows Form Designer generated code " 00008: #End Region 00009: 00010: Private RemoteObj As RemoteObjectInterfaces.IRemoteObject 00011: 00012: Private Sub Form_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 00013: 00014: Try 00015: ' Configure the network channel. 00016: RemotingConfiguration.Configure("Client.exe.config") 00017: Catch x As System.Exception 00018: MsgBox("Не загружена клиентская конфигурация Remoting." & vbCrLf & x.Message) 00019: End Try 00020: 00021: 00022: ' Register the object using the interface and a URL defined 00023: ' in the <appSettings> section of the configuration file. 00024: Dim Obj As Object 00025: Obj = Activator.GetObject( _ 00026: GetType(RemoteObjectInterfaces.IRemoteObject), _ 00027: System.Configuration.ConfigurationSettings.AppSettings("RemoteObjUrl")) 00028: 00029: RemoteObj = CType(Obj, RemoteObjectInterfaces.IRemoteObject) 00030: 00031: Try 00032: ' Access the remote object through the interface. 00033: lblInfo.Text &= vbNewLine & "Object executing in: " & RemoteObj.GetLocation 00034: Catch x As System.Exception 00035: MsgBox("Нет связи с сервером." & vbCrLf & x.Message) 00036: End Try 00037: End Sub 00038: 00039: Private Sub cmdTest_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdTest.Click 00040: Try 00041: 'Вызов метода удаленного обьекта с параметром 00042: TextBox1.Text = RemoteObj.GetSum(TextBox1.Text) 00043: Catch x As System.Exception 00044: MsgBox("Нет связи с сервером." & vbCrLf & x.Message) 00045: End Try 00046: End Sub 00047: End Class
Основная фишка этого текста - активация серверного класса не по NEW (хотя именно так положено по правилам) - а используя его описание интерфейсов - на которые ставится ссылка при компиляции - строки 24-29. Второй момент - загрузка конфигурации извне, причем описание сервиса по идее должно было бы выглядеть вот так:
на самом деле для нашей версии выглядит вот так:
Естественно и конфигурация могла бы обрабатыватся проще (если бы мы сделали доступным клиенту не только описание интерфейсов серверного класса, а весь класс:
00001: RemotingConfiguration.Configure("Client.exe.config") 00002: Dim RemoteObj As New RemoteObjects.RemoteObject()и соответственно в конфигурации можно было бы прямо указывать WELLKNOWN, а не просто дополнительный ключ. В том, что конфигурация клиента из дополнительного ключа загружена правильно мы можем убедится - посмотрев на нее в отладчике.
Когда сервер REMOTING запущен:
то открытый порт мы можем увидеть любым сканером. Теперь только остается запустить клиента на другой машине и наслаждатся прохождением пакетов через сеть. В этом проекте был использован бинарный упаковщик, а он может быть и SOAP (как в Web-службах) или даже написан самолично. Но это более тонкие вещи, чем рассмотренные на этой страничке.
Я выкладываю здесь полностью рабочий вышеописанный проект, который легко расширять дальше в любом направлении...
<SITEMAP> <MVC> <ASP> <NET> <DATA> <KIOSK> <FLEX> <SQL> <NOTES> <LINUX> <MONO> <FREEWARE> <DOCS> <ENG> <CHAT ME> <ABOUT ME> < THANKS ME> |