none
Ошибка при работе с методом Available класса Socket RRS feed

  • Вопрос

  • День добрый! Возникла проблема при работе с методом Available класса Socket.
    Код приведенный ниже отправляет HTTP запрос на сервер. Обычно, этот код работает нормально, т.е. возвращается полный ответ от сервера.
    Если сервер возвращает страницу размером в несколько десятков кб, то возникает проблема. socket.Available становится == 0 еще до того момента, когда страница полностью получена.
    При отладке кода ставлю BreakPoint на слово break; в этой части кода:

     

    if (socket.Available == 0)
        {
         break;
        }
    

     

    Дожидаюсь, пока BreakPoint не сработает. Проверяю Available property и он у меня всегда > 0. Т.е. получается, что условие выполняется неверно.

    Если же вообще убрать код:

    if (socket.Available == 0)
        {
         break;
    }

    то ответ получается нормально (срабатывает Timeout). Все бы хорошо, но времени тратится непозволительно много. Что я делаю не так? И как мне дальше быть?
    Заранее спасибо за помощь.

    Листинг кода:

     

    public class SocketSender
     {
      public Encoding SenderEncoding = Encoding.Default;
      public Encoding ReceiverEncoding = Encoding.Default;
     
      public string ExecuteRequest(string host, int port, string request)
      {
       if (String.IsNullOrEmpty(host)
        || String.IsNullOrEmpty(request)
        || port <= 0)
       {
        return String.Empty;
       }
     
       Socket socket = null;
       IPHostEntry hostEntry = null;
       try
       {
        hostEntry = Dns.GetHostEntry(host);
        foreach (IPAddress address in hostEntry.AddressList)
        {
         IPEndPoint ipe = new IPEndPoint(address, port);
         Socket tempSocket = new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
         tempSocket.Connect(ipe);
         if (tempSocket.Connected)
         {
          socket = tempSocket;
          break;
         }
         else
         {
          continue;
         }
        }
       }
       catch
       {
        //todo do smth
        return String.Empty;
       }
     
       if (socket == null)
       {
        return String.Empty;
       }
     
       Byte[] bytesSent = null;
       Byte[] bytesReceived = null;
     
       try
       {
        bytesSent = SenderEncoding.GetBytes(request);
        bytesReceived = new Byte[256];
        socket.Send(bytesSent, bytesSent.Length, 0);
       }
       catch
       {
        return String.Empty;
       }
     
       int bytes = 0;
       string page = String.Empty;
       socket.ReceiveTimeout = 5000;
       socket.SendTimeout = 5000;
       do
       {
        try
        {
         bytes = socket.Receive(bytesReceived, bytesReceived.Length, 0);
         page = page + ReceiverEncoding.GetString(bytesReceived, 0, bytes);
        }
        catch
        {
         //todo log error
         return page;
        }
        
        if (socket.Available == 0)
        {
         break;
        }
     
       } while (bytes > 0);
     
       return page;
      }
    }
    

     


Ответы

  • Available == 0 - это не признак, что все данные от сервера получены. Единственный верный признак - от сервера получено столько байт, сколько написано в заголовке ответа Content-Length (кроме некоторых случаев, описанных в http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4).

    А костыль со Thread.Sleep будет работать только для быстрого сервера, и обеспечит пару часов незабываемой отладки невоспроизводимых багов.


    My blog | My Favorite Project
    • Помечено в качестве ответа Abolmasov Dmitry 1 июня 2011 г. 7:06
    Модератор

Все ответы