Поток WCF: последний байт потерян - PullRequest
1 голос
/ 21 января 2011

У меня есть служба WCF, у которой есть один метод, возвращающий поток.

[ServiceContract]
public interface IService1
{
    [OperationContract]
    MyMessage Test();
}

Теперь MyMessage определяется следующим образом:

[MessageContract]
public class MyMessage
{
    public MyMessage(string file)
    {
        this.Stream = File.OpenRead(file);
        this.Length = Stream.Length;
    }

    [MessageHeader]
    public long Length;

    [MessageBodyMember]
    public Stream Stream;
}

Peachy.

Служба имеет потоковый ответ, используя basicHttpBinding. Это обязательная конфигурация:

  <basicHttpBinding>
    <binding name="BasicStreaming"
             maxReceivedMessageSize="67108864" maxBufferSize="65536" transferMode="StreamedResponse" />
  </basicHttpBinding>

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

        Service1Client client = new Service1Client();

        //this way the last byte is lost
        Stream stream1;
        var length = client.Test(out stream1);
        var buffer1 = new byte[length];
        stream1.Read(buffer1, 0, (int)length);
        File.WriteAllBytes("test1.txt", buffer1);
        stream1.Close();

        //here i receive all bytes
        Stream stream2;
        length = client.Test(out stream2);
        var buffer2 = new byte[length];
        int c = 0, b;
        while ((b = stream2.ReadByte()) != -1)
        {
            buffer2[c++] = (byte)b;
        }
        File.WriteAllBytes("test2.txt", buffer2);
        stream2.Close();

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

Технические данные:

  • IIS 7.0
  • .NET 3.5
  • Базовая привязка HTTP
  • Режим потоковой передачи

Примечание: Я загрузил проект, изолирующий проблему, так что любой может попробовать его: mediafire

Ответы [ 2 ]

1 голос
/ 21 января 2011

У меня нет точного ответа относительно того, почему это работает (мой мозг не полностью задействован в данный момент), однако это работает:

var buffer1 = new byte[length+2];
stream1.Read(buffer1, 0, buffer1.Length);

(и, да, у вас получается слишком большой буфер. Это просто отправная точка для дальнейших размышлений)

При тестировании я обнаружил, что +1 недостаточно велико, но +2 - достаточно.

0 голосов
/ 21 января 2011

Зачем проходить отсчет (длина + 1)? Длина должна быть длинной, в противном случае вы пытаетесь прочитать на один байт больше, чем доступно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...