WCF и передающие потоком запросы и ответы

Это корректно, который в WCF, я не могу сделать, чтобы сервис записал в поток, который получен клиентом?

Потоковая передача поддерживается в WCF для запросов, ответов или обоих. Я хотел бы поддерживать сценарий, где генератор данных (или клиент в случае переданного потоком запроса или сервер в случае переданного потоком ответа) может Записать на потоке. Это поддерживается?

Аналогией является Ответ. OutputStream от запроса ASP.NET. В ASPNET любая страница может вызвать Write на поток вывода, и содержание получено клиентом. Я могу сделать, что-то подобное в сервисе WCF - вызывает Write на поток, который получен клиентом?

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

[ServiceContract]
public interface IStreamService
{
    [OperationContract]
    Stream GetData(string fileName);
}
public class StreamService : IStreamService
{
    public Stream GetData(string filename)
    {
        return new FileStream(filename, FileMode.Open)
    }
}

И клиентский код похож на это:

StreamDemo.StreamServiceClient client = 
    new WcfStreamDemoClient.StreamDemo.StreamServiceClient();
Stream str = client.GetData(@"c:\path\on\server\myfile.dat");
do {
  b = str.ReadByte(); //read next byte from stream
  ...
} while (b != -1);

(пример, взятый из http://blog.joachim.at/?p=33)

Ясный, правильно? Сервер возвращает Поток клиенту, и клиент вызывает Read на него.

Для клиента действительно ли возможно обеспечить Поток и сервер для вызова Write на него?
Другими словами, а не модель приема - где клиент вытягивает данные из сервера - это - модель передачи, где клиент обеспечивает поток "приемника" и записи сервера в него. Серверный код мог бы выглядеть подобным этому:

[ServiceContract]
public interface IStreamWriterService
{
    [OperationContract]
    void SendData(Stream clientProvidedWritableStream);
}
public class DataService : IStreamWriterService
{
    public void GetData(Stream s)
    {
        do {
          byte[] chunk = GetNextChunk();
          s.Write(chunk,0, chunk.Length);
        } while (chunk.Length > 0); 
    }
}

Действительно ли это возможно в WCF, и если так, как? Что настройки конфигурации требуются для привязки, интерфейса, и т.д.? Какова терминология?

Возможно, это будет просто работать? (Я не попробовал его),

Спасибо.

13
задан Cheeso 28 April 2010 в 03:28
поделиться

2 ответа

Я совершенно уверен, что не существует комбинации привязок WCF, которая позволит вам буквально писать в поток клиента. Кажется логичным, что они должны быть, учитывая, что где-то под поверхностью определенно будет NetworkStream, но как только вы начнете добавлять шифрование и все эти забавные вещи, WCF должен будет знать, как обернуть этот поток, чтобы превратить его в "настоящее" сообщение, чего, как мне кажется, он не делает.

Однако, сценарий I-need-to-return-a-stream-but-component-X-wants-to-write-to-one является общим, и у меня есть универсальное решение, которое я использую для этого сценария, который заключается в создании двустороннего потока и порождении рабочего потока для записи в него. Самый простой и безопасный способ сделать это (под этим я подразумеваю способ, который включает в себя написание наименьшего количества кода и, следовательно, наименьшую вероятность ошибок) - использовать анонимные трубы.

Вот пример метода, возвращающего AnonymousPipeClientStream который можно использовать в WCF-сообщениях, результатах MVC и так далее - везде, где вы хотите изменить направление:

static Stream GetPipedStream(Action<Stream> writeAction)
{
    AnonymousPipeServerStream pipeServer = new AnonymousPipeServerStream();
    ThreadPool.QueueUserWorkItem(s =>
    {
        using (pipeServer)
        {
            writeAction(pipeServer);
            pipeServer.WaitForPipeDrain();
        }
    });
    return new AnonymousPipeClientStream(PipeDirection.In, pipeServer.ClientSafePipeHandle);
}

Пример использования этого метода:

static Stream GetTestStream()
{
    string data = "The quick brown fox jumps over the lazy dog.";
    return GetPipedStream(s =>
    {
        StreamWriter writer = new StreamWriter(s);
        writer.AutoFlush = true;
        for (int i = 0; i < 50; i++)
        {
            Thread.Sleep(50);
            writer.WriteLine(data);
        }
    });
}

Только два предостережения относительно этого подхода:

  1. Он потерпит неудачу, если writeAction сделает что-нибудь для утилизации потока (вот почему метод тестирования не утилизирует StreamWriter - потому что это привело бы к утилизации основного потока);

  2. Он может потерпеть неудачу, если writeAction фактически не записывает никаких данных, потому что WaitForPipeDrain вернется немедленно и создаст состояние гонки. (Если это вызывает беспокойство, вы можете написать более защитный код, чтобы избежать этого, но это сильно усложняет ситуацию для редкого крайнего случая.)

Надеюсь, это поможет в вашем конкретном случае.

9
ответ дан 2 December 2019 в 00:58
поделиться

Потоковая передача WCF работает в обоих направлениях - ваши клиенты могут загружать данные в потоке, но ваша служба WCF также может отправлять данные в потоке. Вы определенно можете написать службу, которая выполняет потоковую передачу больших файлов на основе их имени файла или некоторого идентификатора или чего-то еще - абсолютно.

Если вы хотите отправить данные обратно из службы, вам нужно сделать это в возвращаемом значении вашего метода службы, которое должно иметь тип Stream - вы не можете (насколько мне известно ) «предоставить» поток для записи - служба WCF создаст поток ответа и отправит его обратно.

Проверяли ли вы MSDN Streaming Message Transfer или сообщение в блоге Дэвида Вуда или сообщение в блоге Кьелл-Сверре о потоковой передаче WCF? Все они прекрасно показывают, какие настройки конфигурации вам нужны (в основном установка TransferMode в конфигурации привязки на Streamed , StreamedRequest или StreamedResponse ).

3
ответ дан 2 December 2019 в 00:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: