C #: правильное завершение соединения при отправке данных в WebClient

Мне нужно локально протестировать некоторый код, который использует объект WebClient для связи с http-сервером. Для этого я решил написать невероятно упрощенный фиктивный сервер, который считывает некоторые байты из двоичного файла и отправляет их клиенту. Вот код соответствующего сервера:

public void Listen()
{
    TcpClient client;
    NetworkStream netStream;
    listener.Start();

    try
    {
        client = listener.AcceptTcpClient();
        netStream = client.GetStream();
        ReadData(netStream);
        Console.WriteLine("Writing data, sequence 1");
        WriteData(netStream, 1);
        netStream.Close();
        client.Close();

        client = listener.AcceptTcpClient();
        netStream = client.GetStream();
        ReadData(netStream);
        Console.WriteLine("Writing data, sequence 2");
        WriteData(netStream, 2);
        netStream.Close();
        client.Close();
    }
    catch(Exception e)
    {
    }
}

private void WriteData(NetworkStream netStream, int sequence)
{
    byte[] bytes = PrepareResponse(sequence);    //get data from a file
    netStream.Write(bytes, 0, bytes.Length);
}

С WebClient я использую UploadString:

string response = client.UploadString(address + link, data);

Итак, дело в том, что WebClient, по-видимому, получает все отправленные данные, но выдает исключение System.IO.Exception («Невозможно прочитать данные из транспортного соединения: соединение было закрыто.»), Когда я закрываю поток на стороне сервера. Если я не закрываю поток, WebClient блокируется и ожидает завершения передачи, несмотря на получение всех данных. Я попытался заменить WebClient на WebRequest, и он также либо выдает исключение, если сокет был закрыт на стороне сервера, либо блокируется в потоке. Прочтите после чтения всех данных. Что мне кажется странным, так это то, что первым блоком данных, который я отправляю в WebClient, является ответ http 302 «Перемещено», в результате чего WebClient немедленно отправляет запрос GET. Несмотря на то, что я отправляю данные идентично два раза, WebClient выдает исключение только при втором ответе.

Итак - мне нужен способ правильно отправить данные и закрыть соединение, чтобы оно работало с WebClient, и я также хотел бы знать, почему WebClient правильно обрабатывает ответ 302 и генерирует исключение во втором ответе.

Спасибо.


person sdds    schedule 10.08.2012    source источник
comment
Было бы неплохо сделать несколько дампов фактических данных, которые вы отправляете. Попробуйте Fiddler.   -  person CodeCaster    schedule 10.08.2012
comment
Вы правы, проблема была в отправке данных. Описание проблемы я выложил отдельным ответом.   -  person sdds    schedule 10.08.2012


Ответы (2)


Вы должны попытаться прояснить это с помощью инструкции по использованию: http://msdn.microsoft.com/fr-fr/library/yh598w02.

По сути, такие классы, как NetworkReader, MemeryStream и т. Д., Реализуют интерфейс IDisposable. Если вы оберните их с помощью, он автоматически избавится от объекта для вас.

РЕДАКТИРОВАТЬ: Также, ссылаясь на http://msdn.microsoft.com/fr-fr/library/system.net.sockets.networkstream_methods%28v=vs.80%29 есть метод для чтения и записи потока , вы должны использовать это вместо своего.

person h1ghfive    schedule 10.08.2012

Ответ был на самом деле довольно тривиальным - второй HTTP-ответ имел в заголовках "Transfer-Encoding: chunked", и я фактически не отправлял завершающий фрагмент нулевой длины в конце ответа, поэтому WebClient ждал большего данные.

person sdds    schedule 10.08.2012