Модераторы: Snowy, Poseidon, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Аналог InternetReadFile на сокетах, Скачать то что нужно 
:(
    Опции темы
Maks1509
Дата 13.11.2008, 14:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 54
Регистрация: 22.8.2007
Где: г. Тольятти

Репутация: 2
Всего: 5



Здраствуйте. Необходимо скачать текстовый файл с сервера через сокеты. Раньше использовал WinInet функции. Соединялся, проверял ответ от сервера и заполнял буфер данными, которые потом использовал по назначению.

Код был такой:

Код

function GetTextFileFromServer(szURL : AnsiString) : AnsiString;
var
  FSession  : HINTERNET;
  hConnect  : HINTERNET;
  szBuffer  : Array [0..4095] of AnsiChar;
  dwIndex   : DWORD;
  dwCodeLen : DWORD;
  hRequest  : LongBool;
  szNotify  : AnsiString;
  dwTimeout : Integer;
  dwRead    : Cardinal;
begin
  Result := '';
  try
    { открываем интернет сессию для выполнения последующих действий }
    FSession := InternetOpen('Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
    { устанавливаем таймер на сессию - 10 секунд }
    dwTimeout := 10 * 1000;
    InternetSetOption(FSession, INTERNET_OPTION_CONNECT_TIMEOUT, @dwTimeout, SizeOf(dwTimeout));
    InternetSetOption(FSession, INTERNET_OPTION_RECEIVE_TIMEOUT, @dwTimeout, SizeOf(dwTimeout));
    InternetSetOption(FSession, INTERNET_OPTION_SEND_TIMEOUT, @dwTimeout, SizeOf(dwTimeout));
    if FSession <> nil then
    try
      { получаем хэндл открытого файла по сети }
      hConnect := InternetOpenUrl(FSession, PAnsiChar(szURL), nil, 0, INTERNET_FLAG_NO_UI, 0);
      if hConnect <> nil then
      try
        { проверяем открытое соединение на ошибки }
        dwIndex  := 0;
        dwCodeLen := Length(szBuffer);
        hRequest := HttpQueryInfo(hConnect, HTTP_QUERY_STATUS_CODE, @szBuffer[0], dwCodeLen, dwIndex);
        if hRequest then
          begin
            szNotify := szBuffer;
            { если код ошибки 200 - все прошло нормально и продолжаем }
            if szNotify = '200' then
              begin
                repeat
                  FillChar(szBuffer, SizeOf(szBuffer), 0);
                  if InternetReadFile(hConnect, @szBuffer[0], SizeOf(szBuffer), dwRead) then
                    Result := Result + szBuffer
                  else
                    Break;
                until
                  dwRead = 0;
              end;
          end;
      finally
        InternetCloseHandle(hConnect);
      end;
    finally
      InternetCloseHandle(FSession);
    end;
  except
  end;
end;


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

Решил скачивать файл через сокеты. Посмотрел что люди пишут и решил написать код:

Код

function GetHttpData(szURL, szMethod : AnsiString; dwPort : WORD; szArgs, szContent : AnsiString) : AnsiString;
var
  hSocket  : TSocket;
  SockAddr : TSockAddr;
  szBuffer : Array [0..1023] of AnsiChar;
  BuffSize : Cardinal;
  WSAData  : TWSAData;
  szTemp   : AnsiString;
  szHost   : AnsiString;
  sHostEnt : PHostEnt;
  sTimeout : Integer;
begin
  { возвращаем пустой результат в функцию }
  Result := '';
  { извлекаем название хоста для соединения }
  szTemp := szURL;
  if Pos('//', szTemp) > 0 then
    Delete(szTemp, 1, Pos('//', szTemp) + 1);
  szHost := Copy(szTemp, 1, Pos('/', szTemp) - 1);
  { запускаем библиотеку winsock версии 2 }
  if WSAStartup(MAKEWORD(2, 0), WSAData) <> NOERROR then
    Exit;
  { пытаемся извлечь название хоста }
  sHostEnt := GetHostByName(PAnsiChar(szHost));
  if sHostEnt = nil then
    begin
      WSACleanup;
      Exit;
    end;
  { создаем сокет с нужными нам параметрами }
  hSocket := socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
  if hSocket = INVALID_SOCKET then
    begin
      WSACleanup;
      Exit;
    end;
  FillChar(SockAddr, SizeOf(sockaddr_in), 0);
  SockAddr.sin_family := AF_INET;
  SockAddr.sin_addr   := PInAddr(sHostEnt^.h_addr_list^)^;
  SockAddr.sin_port   := htons(dwPort);
  { устанавливаем интервалы таймаута }
  sTimeout := 1000000;
  setsockopt(hSocket, SOL_SOCKET, SO_RCVTIMEO, @sTimeout, SizeOf(Integer));
  setsockopt(hSocket, SOL_SOCKET, SO_SNDTIMEO, @sTimeout, SizeOf(Integer));
  { если не удалось соединиться - останавливаемся }
  if connect(hSocket, SockAddr, SizeOf(SockAddr)) = SOCKET_ERROR then
    begin
      shutdown(hSocket, SD_BOTH);
      closesocket(hSocket);
      WSACleanup;
      Exit;
    end;  { формируем строку для отправки запроса }
  szTemp := Format('%s %s HTTP/1.1' + sLineBreak +
                   '%s' + sLineBreak +
                   'User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)' + sLineBreak +
                   'Host: %s' + sLineBreak +
                   'Content-Length: %s' + sLineBreak +
                   'Connection: Keep-Alive' + sLineBreak +
                   'Cache-Control: no-cache' + sLineBreak + sLineBreak +
                   szArgs, [szMethod, szURL, szContent, szHost, IntToStr(Length(szArgs))]);
  { отправляем через сокет запрос }
  if send(hSocket, Pointer(szTemp)^, Length(szTemp), 0) = SOCKET_ERROR then
    begin
      shutdown(hSocket, SD_BOTH);
      closesocket(hSocket);
      WSACleanup;
      Exit;
    end;
  { получаем результат и сохраняем его }
  FillChar(szBuffer, SizeOf(szBuffer), 0);
  repeat
    BuffSize := recv(hSocket, szBuffer, SizeOf(szBuffer), 0);
    if BuffSize > 0 then
      begin
        Result := Result + PAnsiChar(@szBuffer);
        FillChar(szBuffer, SizeOf(szBuffer), 0);
      end;
  until
    BuffSize > 0;
  { очищаем буфер, закрываем сокет и выгружаем winsock }
  FillChar(szBuffer, SizeOf(szBuffer), 0);
  shutdown(hSocket, SD_BOTH);
  closesocket(hSocket);
  WSACleanup;
end;

Вроде бы все работает нормально. Вслучае неудачного соединения или какой-то ошибки сокет благополучно закрывается.

Вопрос следующий. Я хочу скачать текстовый файл с сервера и получить в результате только именно текст, находящийся в этом файле. Естественно приходит информация побольше, содержащая всякие Content-Type, Keep-Alive, Content-Length и какие-то цифры/буквы посреди которых данные с текстового файла. Как мне выцепить только эти данные?

На 200 код сделал такую проверку. Кусок кода:

Код

 s := GetHttpData('ссылка', 'GET', 80, '', 'Content-Type: text/plain');
  if Pos('HTTP/1.1 200 OK', s) > 0 then
    begin
      p := Pos(#13#10 + #13#10, s);
      s := Copy(s, p + 4, Length(s) - p + 4);
    end
  else
    s := 'пусто';


Может быть как-то еще можно выполнить проверку на удачность соединения? Или как-то в параметрах подключения у сокетов указать?

Спасибо.
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Сети"
Snowy
Poseidon
MetalFan

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делится вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи

Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Snowy, Poseidon, MetalFan.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.0385 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.