Пользовательский .NET Remoting IServerChannelSink - PullRequest
2 голосов
/ 17 августа 2011

У меня есть клиент-серверное приложение, которое использует связь .NET Remoting. Из соображений аутентификации мне пришлось написать пользовательский IClientChannelSink , чтобы вставить сессионный cookie в HTTP-запросы. На стороне сервера я также написал пользовательский IServerChannelSink для чтения некоторой информации, которая нужна серверу, из заголовков HTTP-запроса.

Клиентская сторона работает нормально, но на серверной стороне я всегда получаю следующую ошибку:

System.ArgumentNullException не было обработано кодом пользователя Сообщение = Нет сообщение было десериализовано до вызова DispatchChannelSink. Имя параметра: requestMsg Source = mscorlib ParamName = requestMsg
Трассировки стека: в System.Runtime.Remoting.Channels.DispatchChannelSink.ProcessMessage (IServerChannelSinkStack SinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Поток requestStream, IMessage & responseMsg, ITransportHeaders & responseHeaders, Stream & responseStream) в MyAuthentication.MyServerChannelSink.ProcessMessage (IServerChannelSinkStack SinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Поток requestStream, IMessage & responseMsg, ITransportHeaders & responseHeaders, Stream & responseStream) в C: \ Dev \ MyAuthentication \ MyServerChannelSink.cs: строка 82 в System.Runtime.Remoting.Channels.BinaryServerFormatterSink.ProcessMessage (IServerChannelSinkStack SinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Поток requestStream, IMessage & responseMsg, ITransportHeaders & responseHeaders, Stream & responseStream) в System.Runtime.Remoting.Channels.Http.HttpServerTransportSink.ServiceRequest (Объект государство) в System.Runtime.Remoting.Channels.SocketHandler.ProcessRequestNow ()
InnerException:

Мой метод "ProcessMessage" выглядит следующим образом:

public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream)
{
    // Pre-processing before sending the message to the next sink in the chain
    object state = null;
    ProcessRequest(requestMsg, requestHeaders, ref requestStream, ref state);

    /* Call the next sink in the chain */
    sinkStack.Push(this, state);
    ServerProcessing serverProcessing = this.NextChannelSink.ProcessMessage(sinkStack, requestMsg, requestHeaders, requestStream, out responseMsg, out responseHeaders, out responseStream);

    // Processing from sink further in the chain has completed. Now do any post-processing before returning to the previous sink in the chain.
    ProcessResponse(null, responseHeaders, ref responseStream, state);

    return serverProcessing;
}

Было бы замечательно, если бы кто-нибудь мог сказать мне, что случилось.

Ответы [ 3 ]

2 голосов
/ 17 августа 2011

При определенных обстоятельствах параметр requestMsg может быть нулевым.Таким образом, вы должны разобраться с этими случаями.Например, другой приемник канала сервера вызывает вашу функцию ProcessMessage с параметром requestMsg, установленным в null!

РЕДАКТИРОВАТЬ: Предоставлена ​​ссылка на образец.Вот ссылка на образец приемника сервера: Server Sink

0 голосов
/ 10 июля 2013

Создав свой серверный канал

TcpServerChannel oTcpChannel =
    new TcpServerChannel(oTcpChannelConfiguration, oServerSinkProvider, oAuthority);

Вы можете установить oServerSinkProvider = null, и система будет поддерживать поставщика приемников по умолчанию.Вы также можете указать свой собственный форматер, например, мыльный форматер для канала TCP или двоичный форматер для канала http: SoapServerFormatterSinkProvider или BinaryServerFormatterSinkProvider.

Однако, если вы поддерживаете свой собственный приемник сервера, вы должны также реализовать свой собственный форматтер.Вы можете сделать это в разделе настроек вашей функции IServerChannelSinkProvider.Next с помощью:

  set
  {
    if ( value != null )
    {
      nextProvider = new BinaryServerFormatterSinkProvider ();
      nextProvider.Next = value;
    }
    else
    {
      nextProvider = value;
    };
  }

Тогда следующий провайдер выполнит работу по форматированию, в этом случае двоичному форматированию.

0 голосов
/ 19 августа 2011

Я решил свою проблему. Поскольку я не использую приемники каналов для какой-либо сериализации, я также не хочу самостоятельно обрабатывать десериализацию сообщений. Следующая реализация работает нормально:

public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream)
{
    // Pre-processing before sending the message to the next sink in the chain
    object state = null;
    ProcessRequest(requestMsg, requestHeaders, ref requestStream, ref state);

    ServerProcessing serverProcessing;
    if (requestMsg != null)
    {
        /* Call the next sink in the chain */
        sinkStack.Push(this, state);
        serverProcessing = this.NextChannelSink.ProcessMessage(sinkStack, requestMsg, requestHeaders, requestStream, out responseMsg, out responseHeaders, out responseStream);
        sinkStack.Pop(this);
    }
    else
    {
        responseMsg = null;
        responseHeaders = null;
        responseStream = null;
        serverProcessing = ServerProcessing.Complete;
    }

    // Processing from sink further in the chain has completed. Now do any post-processing before returning to the previous sink in the chain.
    ProcessResponse(null, responseHeaders, ref responseStream, state);

    return serverProcessing;
}
...