Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.138.114.94] |
|
Сообщ.
#1
,
|
|
|
Здрасте, сначала старая проблема с приведением интерфейса, порылся как посоветовали, нашел 2 атрибута, но так ничё умного и не смог с ними сотворить
Несколько новых вопросов: 1) Можно ли на сервере так публиковать исключение, что бы его был обязан обработать клиент? 2) Как можно "прихлопнуть" клиента, т.е. закрыть все объекты что он открыл по ссылке? Я так понимаю это как то связанно с временем жизни объекта класса MarshalByRefObject? 3) Как узнать удалённый ип в сессии с клиентом? |
Сообщ.
#2
,
|
|
|
Цитата TerraGhost @ 1) Можно ли на сервере так публиковать исключение, что бы его был обязан обработать клиент? Шарп не джава, заставить когото обрабатывать исключения нельзя. Цитата TerraGhost @ 2) Как можно "прихлопнуть" клиента, т.е. закрыть все объекты что он открыл по ссылке? Я так понимаю это как то связанно с временем жизни объекта класса MarshalByRefObject? Раз ты используешь MarshalByRefObject следовательно не совсем то и ссылку на объект ты получаешь. Реально ты работаешь через прокси Transparent Proxy, читай соответсвующую литературу. Что касается времени жизни объекта, то ты не переживай. В зависимости от того, в каком режиме ты запустил сервер. Объекты живут либо время обработки запроса и на каждый из них реагирует собственный инстанс сервера(SingleCall) либо все запросы обслуживает один инстанс (Singleton, правда что бы он не пересоздавался нужно переопределить метод InitializeLifetimeService) public class RemoteObject: MarshalByRefObject { //если этого не сделать то через пять минут простоя в режиме Singleton, будет создан новый инстанс класса RemoteObject public override object InitializeLifetimeService() { return null; } } Цитата TerraGhost @ Как узнать удалённый ип в сессии с клиентом? Веди на сервере список клиентов. P.S. Скорее всего тебе прийдется разобраться как работать с приемниками (Sink). До IP адреса легко добраться именно там получив доступ к заголовкам транспортного протокола IPAddress clientAddress = requestHeaders[CommonTransportKeys.IPAddress] as IPAddress; в этом коде requestHeaders это переменная которая реализует интерфейс ITransportHeaders доступная в стандартном для приемников методе обработки сообщений ProcessMessage (серверные приемники обязаны реализовывать интерфейсс IServerChannelSink, вот он то и требует реализовывать этот метод) Добавлено using System; using System.Collections; using System.IO; using System.Net; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Messaging; namespace ClassLibRemotingIPSink { public class ClientIPServerSinkProvider : IServerChannelSinkProvider { private IServerChannelSinkProvider next = null; public ClientIPServerSinkProvider(IDictionary properties, ICollection providerData) { } public void GetChannelData(IChannelDataStore channelData) { } public IServerChannelSink CreateSink(IChannelReceiver channel) { IServerChannelSink nextSink = null; if (next != null) { nextSink = next.CreateSink(channel); } return new ClientIPServerSink(nextSink); } public IServerChannelSinkProvider Next { get { return next; } set { next = value; } } } public class ClientIPServerSink : BaseChannelObjectWithProperties, IServerChannelSink, IChannelSinkBase { private IServerChannelSink _next; public ClientIPServerSink(IServerChannelSink next) { _next = next; } public void AsyncProcessResponse(System.Runtime.Remoting.Channels.IServerResponseChannelSinkStack sinkStack, System.Object state, System.Runtime.Remoting.Messaging.IMessage msg, System.Runtime.Remoting.Channels.ITransportHeaders headers, System.IO.Stream stream) { } public Stream GetResponseStream(System.Runtime.Remoting.Channels.IServerResponseChannelSinkStack sinkStack, System.Object state, System.Runtime.Remoting.Messaging.IMessage msg, System.Runtime.Remoting.Channels.ITransportHeaders headers) { return null; } public System.Runtime.Remoting.Channels.ServerProcessing ProcessMessage(System.Runtime.Remoting.Channels.IServerChannelSinkStack sinkStack, System.Runtime.Remoting.Messaging.IMessage requestMsg, System.Runtime.Remoting.Channels.ITransportHeaders requestHeaders, System.IO.Stream requestStream, out System.Runtime.Remoting.Messaging.IMessage responseMsg, out System.Runtime.Remoting.Channels.ITransportHeaders responseHeaders, out System.IO.Stream responseStream) { if (_next != null) { IPAddress ip = requestHeaders[CommonTransportKeys.IPAddress] as IPAddress; if (ip != null) { Console.WriteLine(ip.ToString()); CallContext.SetData("ClientIPAddress", ip); } ServerProcessing spres = _next.ProcessMessage(sinkStack, requestMsg, requestHeaders, requestStream, out responseMsg, out responseHeaders, out responseStream); return spres; } else { responseMsg = null; responseHeaders = null; responseStream = null; return new ServerProcessing(); } } public IServerChannelSink NextChannelSink { get { return _next; } set { _next = value; } } } } Код реализует серверный приемник где происходит извлечение IP клиента из заголовка транспортного протокола. Затем айпишник помещается в контекст вызова. Это позволит тебе потом легко к нему добраться из кода сервера, или же можешь производить с ними всю работу прям в приемнике. Подключаются приемники в инфраструктуру Remoting через конфигурационные файлы. <system.runtime.remoting> <application> ............................................ <channels> <channel ref="http" port="8124"> <serverProviders> <provider type="ClassLibRemotingIPSink.ClientIPServerSinkProvider, ИмяСборки" /> <formatter ref="binary" /> </serverProviders> </channel> </channels> </application> </system.runtime.remoting> Думаю проблем у тебя быть не должно. Но почитать о приемниках всеравно настоятельно рекомендую. |
Сообщ.
#3
,
|
|
|
1)
Цитата Шарп не джава, заставить когото обрабатывать исключения нельзя. Я не совсем ясно выразился, мне нужно сделать так, что бы исключение вызвалось на клиентской стороне, так как придумывать енумы с кодами возврата функции немного гиморно. Это можно или нет? 2)Опять не туда. Мне нужно сотворить блокировку всех вызовов от удалённого объекта на сервере. Это можно сделать с помощью проверок в начале каждой функции, что такой-то клиент, умеет право вызывать эту функцию, либо, как-то прикрыть сетевое соединение сразу. 3) спс, погляжу Ничё там с приведение интерфесов никак? меня это просто убивает |
Сообщ.
#4
,
|
|
|
Цитата TerraGhost @ Я не совсем ясно выразился, мне нужно сделать так, что бы исключение вызвалось на клиентской стороне, так как придумывать енумы с кодами возврата функции немного гиморно. Это можно или нет? Почему нет? У нас с этим проблем никогда не было. Все исключения объявляешь в отельной сборке, цепляешь ее и к серверу и к клиенту. Пробрасываешь на сервере обрабатываешь уже на клиенте. Цитата TerraGhost @ Опять не туда. Мне нужно сотворить блокировку всех вызовов от удалённого объекта на сервере. Это можно сделать с помощью проверок в начале каждой функции, что такой-то клиент, умеет право вызывать эту функцию, либо, как-то прикрыть сетевое соединение сразу. Ну надо не методы прятать от клиента, а реализовать ему авторизацию на доступ к соответствующим методам. Читай в инете много инфы про авторизацию и про аутентификацию в ремотинге. Для декларативной модели в общем случае проведя аутентификацию ты получишь роли клиента, а методы метяться атрибутами по принципу эти роли имеют доступ, а эти нет к этому методу. В императивной модели сможешь проверять кодом не используя атрибуты. Вобщем читай. |
Сообщ.
#5
,
|
|
|
Цитата Почему нет? У нас с этим проблем никогда не было. Все исключения объявляешь в отельной сборке, цепляешь ее и к серверу и к клиенту. Пробрасываешь на сервере обрабатываешь уже на клиенте. Что я не так делаю? Общая бибилиотека public interface IServer { void ExceptionFunction (); } public class MyException : Exception { } Сервер internal static class Program { internal static void Main () { Server.Start (); Console.ReadKey (); } } public class Server : MarshalByRefObject, IServer { public static void Start () { BinaryServerFormatterSinkProvider provider = new BinaryServerFormatterSinkProvider (); provider.TypeFilterLevel = TypeFilterLevel.Full; IDictionary props = new Hashtable (); props["port"] = 12345; TcpChannel channel = new TcpChannel (props, null, provider); ChannelServices.RegisterChannel (channel, false); RemotingConfiguration.RegisterWellKnownServiceType (typeof (Server), "Server", WellKnownObjectMode.Singleton); } public void ExceptionFunction () { throw new MyException (); } } Клиент internal static class Program { internal static void Main () { BinaryServerFormatterSinkProvider provider = new BinaryServerFormatterSinkProvider (); provider.TypeFilterLevel = TypeFilterLevel.Full; IDictionary props = new Hashtable (); props["port"] = 0; TcpChannel channel = new TcpChannel (props, new BinaryClientFormatterSinkProvider (), provider); ChannelServices.RegisterChannel (channel, false); IServer server = (IServer)Activator.GetObject (typeof (IServer), "tcp://localhost:12345/Server"); try { server.ExceptionFunction (); } catch (MyException) { Console.WriteLine ("Ошибка перехвачена"); } Console.ReadKey (); } } И как это исключение "пробросить" на клиент? Цитата Ну надо не методы прятать от клиента, а реализовать ему авторизацию на доступ к соответствующим методам. Читай в инете много инфы про авторизацию и про аутентификацию в ремотинге. Для декларативной модели в общем случае проведя аутентификацию ты получишь роли клиента, а методы метяться атрибутами по принципу эти роли имеют доступ, а эти нет к этому методу. В императивной модели сможешь проверять кодом не используя атрибуты. Вобщем читай. Т.е. и поя предыдущая проблема с привредением интерфеса к Disposabe решается, решается назначением функции Dispose на сервере с максимальным уровнем доступа? |
Сообщ.
#6
,
|
|
|
Цитата TerraGhost @ И как это исключение "пробросить" на клиент? Для начала пометь MyException атрибутом [Serializable] А там уже посмотрим пробрасывается или нет. Вообще все собственные типы, что ты собираешься передавать нужно им отмечать. Или же реализовывать сериализацию, через ISerializable. Вот те рабочая рыба: using System; using System.Security.Permissions; using System.Runtime.Remoting; using System.Runtime.Serialization; namespace Exception.CustomRemotingException { [Serializable] public class CustomRemotingException : RemotingException, ISerializable { public CustomRemotingException () { } public CustomRemotingException (string message) : base(message) { } public CustomRemotingException (string message, System.Exception innerException) : base(message, innerException) { } protected CustomRemotingException (SerializationInfo info, StreamingContext context) : base(info, context) { } public override void GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); } } } Цитата TerraGhost @ Т.е. и поя предыдущая проблема с привредением интерфеса к Disposabe решается, решается назначением функции Dispose на сервере с максимальным уровнем доступа? Вероятно да. Но вообще я не вижу смысла реализовывать IDisposible для Server, обоснуй зачем это может понадобиться. Чисть не управляемые ресурсы или же если хош все руками, то объекты которые создаешь и юзаешь в Server , а самому Server зачем это? |
Сообщ.
#7
,
|
|
|
Цитата Вот те рабочая рыба: Сереализовал класс - толку 0, подставил уже сереализованный базовый Exception - толку 0, как бы не извращался, исключение всё равно выбрасывается на сервере. Цитата Вероятно да. Но вообще я не вижу смысла реализовывать IDisposible для Server, обоснуй зачем это может понадобиться. Чисть не управляемые ресурсы или же если хош все руками, то объекты которые создаешь и юзаешь в Server , а самому Server зачем это? Это называется программная логика, у меня в программе все клиенты тоже умеют друг на друга ограниченную видимость в режиме чтения (посредством интерфейсов нижнего уровня), если они будут друг друга приводить к высшим уровням доступа посредством интерфейсов будет чёрт знает что. Вот мне зачем это. |
Сообщ.
#8
,
|
|
|
TerraGhost, есть еще один тооненький нюанс для проброса исключений с сервера к клиенту :
в конфиг нужно добавить: <system.runtime.remoting> <customErrors mode="off"/> Добавлено Это добавляется в App.config твоего приложения сервера ремотинг, кроме того, как было сказанно: 1. Исключение должно уметь сериализоваться (если оно твое), стандартные уже умеют, их учить не нужно 2. Клиент ремотинг должен знать о типе исключения, которое прилетит, иначе он не сможет его десериализовать. Спсб за внимание |
Сообщ.
#9
,
|
|
|
Цитата PIL @ в конфиг нужно добавить: <system.runtime.remoting> <customErrors mode="off"/> Hi, PIL именно:) |
Сообщ.
#10
,
|
|
|
Помогло, всем спасибо.
|
Сообщ.
#11
,
|
|
|
Кстати убиваеца сцылка на объект методом RemotingServices.Disconnect
|