Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Скриптовые языки программирования > PHP
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 22.01.2011, 13:57   #1
Altera
Старожил
 
Аватар для Altera
 
Регистрация: 29.01.2008
Сообщений: 2,406
По умолчанию Работа с HTTP из C#

Всем привет.
Сегодня разбирался с HTTP, есть сервер с апачем и я написал ещё своего клинта на C#

Код:
 private void sendBtn_Click(object sender, EventArgs e) {
      TcpClient client = new TcpClient(addressBox.Text, 80);

      NetworkStream ns = client.GetStream();

      StreamWriter sw = new StreamWriter(ns, Encoding.Default);
      sw.Write(queryBox.Text);
      sw.Write("\n\n");
      sw.Flush();
      sw.Close();

      StreamReader sr = new StreamReader(ns, Encoding.Default);
      answerBox.Text = sr.ReadToEnd();

      client.Close();
    }
Вводится адрес сервера, заголовки и запрос в отдельном поле и ответ получаем в третьем поле.

С текстом всё ОК но мне захотелось скачать таким способом картинку.
Код:
private void implementAndSaveBtn_Click(object sender, EventArgs e) {         
      TcpClient client = new TcpClient(addressBox.Text, 80);

      NetworkStream ns = client.GetStream();

      StreamWriter sw = new StreamWriter(ns, Encoding.Default);
      sw.Write(queryBox.Text);
      sw.Write("\n\n");
      sw.Flush();
      //sw.Close();

      StreamReader sr = new StreamReader(ns, Encoding.Default);

      Int32 dataLength;
      string answerText = "";


      string headerline;
      while ((headerline = sr.ReadLine()).Length > 0) {
        answerText += (headerline + "\r\n");
      }
      answerText += (headerline + "\r\n");
      
      answerBox.Clear();                               
      answerBox.Text = answerText;

      Regex re = new Regex(@"(?<=Content-Length:\s)\d+", RegexOptions.IgnoreCase);
      Match match = re.Match(answerText);
      dataLength = int.Parse(match.Value);   

      if (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
        BinaryReader br = new BinaryReader(ns);

        FileStream fs = new FileStream(saveFileDialog1.FileName, FileMode.Create);        
        BinaryWriter bw = new BinaryWriter(fs);

        byte[] buffer = br.ReadBytes(dataLength);

        bw.Write(buffer); 

        bw.Flush();
        bw.Close();
        fs.Close();

        br.Close();        
      }             

      client.Close();
    }
короче получается хрень. И не только с картинкой, и с другими файлами пробовал. Отсекается то начало, то конец. Думал заморочки самого HTTP, но потом решил реализовать на Delphi

Код:
procedure TForm1.Button1Click(Sender: TObject);
var
  I: byte;
  rep: string;

  size: dword;

  fileStream: tFileStream;


begin
  IdTCPClient1.Host := edit1.Text;
  IdTCPClient1.Port := 80;

  IdTCPClient1.Connect;

  for I := 0 to memo1.Lines.Count - 1 do
    IdTCPClient1.IOHandler.WriteLn(memo1.Lines.Strings[i]);

  IdTCPClient1.IOHandler.WriteLn(#13#10#13#10);

  repeat
    rep := IdTCPClient1.IOHandler.ReadLn();
    memo2.Lines.Add(rep);
  until (rep = '');

  size := 547315;

  if saveDialog1.Execute then
  begin
    fileStream := tFileStream.Create(saveDialog1.FileName, fmCreate);
    IdTCPClient1.IOHandler.ReadStream(fileStream, size);
    fileStream.Free;
  end;

  IdTCPClient1.Disconnect;
end;
Тут просто короче, без поиска строки Content-Length, я в ручную задал размер файла, то на C# он тоже точно определяется. Короче на Delphi всё работает без проблем. Почему с C#-ом не получается?

p.s. Ни дай бог кто-то предложит мне использовать WebClient-а или что-то подобное. Через WebClient-а само собой работает. Меня интересует почему именно в такой ситуации не работает!
Altera вне форума Ответить с цитированием
Старый 23.01.2011, 06:47   #2
Altera
Старожил
 
Аватар для Altera
 
Регистрация: 29.01.2008
Сообщений: 2,406
По умолчанию

Так, и без вас разобрался.
Сделал всё через BinaryReader
Код:
    private void requireBtn_Click(object sender, EventArgs e) {
      string host = "atomAltera.SkyHost.ge";
      string query = "GET /mems.txt HTTP/1.1\r\n" +
                     "Host: atomAltera.SkyHost.ge\r\n" +
                     "User-Agent: NuclightWeb\r\n" +
                     "Connection: close\r\n"+
                     "\r\n";

      var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
      client.Connect(host, 80);   
        
      var networkStream = new NetworkStream(client);

      var bytes = Encoding.Default.GetBytes(query);
      networkStream.Write(bytes, 0, bytes.Length);


      var bReader = new BinaryReader(networkStream, Encoding.Default);

      string responce = "";
      string line;
      char c;
      
      do {
        line = "";
        c = '\u0000';
        while (true) {
          c = bReader.ReadChar();
          if (c == '\r')
            break;
          line += c;
        }
        c = bReader.ReadChar();
        responce += line + "\r\n";
      } while (line.Length > 0);  

      responceBox.Text = responce;

      Regex reContentLength = new Regex(@"(?<=Content-Length:\s)\d+", RegexOptions.IgnoreCase);
      Int32 contentLength = Int32.Parse(reContentLength.Match(responce).Value);

      this.Text = contentLength.ToString();

      var fileStream = new FileStream(@"C:\m.txt", FileMode.Create);
      
      byte[] buffer = new byte[4 * 1024];
      int n = 0;
      int read = 0;

      while (n < contentLength) {
        if (networkStream.DataAvailable) {
          read = networkStream.Read(buffer, 0, buffer.Length);
          n += read;
          fileStream.Write(buffer, 0, read);
        }
      }

      fileStream.Flush();
      fileStream.Close();      

      client.Close();
    }
Видимо StreamReader что-то там лишнее считывал...
Altera вне форума Ответить с цитированием
Старый 23.01.2011, 08:42   #3
BOBAH13
Android Developer
Старожил Подтвердите свой е-майл
 
Аватар для BOBAH13
 
Регистрация: 19.02.2007
Сообщений: 3,708
По умолчанию

Еще маленький совет, вот тут можно добавить
Код:
while (n < contentLength) {
        if (networkStream.DataAvailable) {
          read = networkStream.Read(buffer, 0, buffer.Length);
          n += read;
          fileStream.Write(buffer, 0, read);
        } else {
          Thread.Sleep(10);
        }
      }
BOBAH13 вне форума Ответить с цитированием
Старый 23.01.2011, 11:02   #4
Altera
Старожил
 
Аватар для Altera
 
Регистрация: 29.01.2008
Сообщений: 2,406
По умолчанию

Цитата:
Сообщение от BOBAH13 Посмотреть сообщение
Еще маленький совет, вот тут можно добавить
Код:
while (n < contentLength) {
        if (networkStream.DataAvailable) {
          read = networkStream.Read(buffer, 0, buffer.Length);
          n += read;
          fileStream.Write(buffer, 0, read);
        } else {
          Thread.Sleep(10);
        }
      }
Да, я думал об этом. Даже можно по больше сделать, особенно если в отдельном потоке качается.

Это вообще они хорошо придумали. Считывается только то что уже есть в буфере. Это как называется, неблокирующие сокеты? Indy бы например заблокировал бы поток пока не скачал указанное число байт, а тут гибкость больше.
Altera вне форума Ответить с цитированием
Старый 23.01.2011, 11:43   #5
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
Это как называется, неблокирующие сокеты?
нет это по прежнему блокирующий.
просто более оптимизированное ожидание данных.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 23.01.2011, 11:50   #6
BOBAH13
Android Developer
Старожил Подтвердите свой е-майл
 
Аватар для BOBAH13
 
Регистрация: 19.02.2007
Сообщений: 3,708
По умолчанию

Цитата:
Сообщение от Altera Посмотреть сообщение
Да, я думал об этом. Даже можно по больше сделать, особенно если в отдельном потоке качается.

Это вообще они хорошо придумали. Считывается только то что уже есть в буфере. Это как называется, неблокирующие сокеты? Indy бы например заблокировал бы поток пока не скачал указанное число байт, а тут гибкость больше.
Ну да, можно еще таймаут прицепить, а то цикл может быть вечным, если к примеру оборвется связь.
BOBAH13 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
работа MySQL через HTTP-proxy programmer1988 Работа с сетью в Delphi 2 13.08.2010 20:35
http hello88 Работа с сетью в Delphi 10 22.07.2010 11:21
http http1 Общие вопросы C/C++ 1 21.07.2010 15:07
Http Proxy - как написать к браузеру http-прокси? SergeiGuk Общие вопросы .NET 0 21.05.2010 17:37
http.Get Domovoy Работа с сетью в Delphi 2 21.11.2007 18:37