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

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

Вернуться   Форум программистов > Delphi программирование > Работа с сетью в Delphi
Регистрация

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 23.09.2007, 22:45   #1
Маркъ
Пользователь
 
Регистрация: 02.02.2007
Сообщений: 32
Вопрос Подвисание программы

При написании программ на indy в некоторых случаях происходит подвисание интерфейса, он просто замораживается, как избежать такого?
P.S. Компонент idAntiFrize почему-то не работает, проверено горьким опытом. Если можно отвечайте подробнее.
Маркъ вне форума Ответить с цитированием
Старый 24.09.2007, 09:52   #2
Квэнди
Старожил
 
Аватар для Квэнди
 
Регистрация: 13.12.2006
Сообщений: 3,859
По умолчанию

Ну собственно причина может быть в нескольких направленияхзависящих именно от Indy и не зависящих именно от Indy %)
1. Если ты не поленился и почитал первую тему раздела, то ты должен знать, что Indy использует принципе "блокирующих сокетов" точнее этот принцип используется в самой ОС.
Что такое принцип блокирующих сокетов?
Это понятие означает, что в момент отправки запроса по сети ( с использованием сокета) программа не продолжит свою работу, пока не получит ответа. Собственно это основная причина "зависания" программ. Да, для "обхода" этого не самого приятного факта был написан компонент idAntiFrize, который признан имитировать принцип "неблокирующих" сокетов, релизованный в операционных системах *nix. На самом деле этот компонент разумеется не позволяет тебе работать именно с неблокирующими сокетами, а лишь имитирует это (всего лишь с помощью дополнительных потоков). Но абсолютно не обязательно что это тебе поможет.
Зачастую диагностируются подобные ошибки очень просто: если программа "зависла" при работе с сетью, то Indy после того как пройдет время "тайм-аут"-а (которое зависит от каждого протокола в отдельности, описано в RFC соответствующего протокола, а в большинстве случаев Time-out настраивается в самом компоненте Indy),
Indy вернет тебе ответ сервера (или ошибку).
2-й вариант причины "зависания" описывать бесполезно, ибо это может быть что угодно.

Вобщем если это тебе не помогло, то выкладывай код, посмотрим.
ICQ не для вопросов, а для предложений. Для вопросов используйте форум
IRC канал клуба программистов|Мои статьи
Квэнди вне форума Ответить с цитированием
Старый 24.09.2007, 14:22   #3
Маркъ
Пользователь
 
Регистрация: 02.02.2007
Сообщений: 32
По умолчанию

Цитата:
Сообщение от Квэнди Посмотреть сообщение
Если ты не поленился и почитал первую тему раздела...
Вобщем если это тебе не помогло, то выкладывай код, посмотрим.
Книгу я прочитал почти полностью, про режимы знаю. Можно ли вообще реализовать то, чтобы программа не подвисала? Не обязательно чтобы это был indy.
Код в общем то примитивный - определение пинга.
Код:
try
ICMP.Ping;
  a[CheckPing]:=icmp.ReplyStatus.MsRoundTripTime;
  if a[CheckPing]>=5000 then
  begin
  Memo1.Lines.Add('Превышен интервал ожидания для запроса');
  errors:=true;
  end
  else
  begin
  Memo1.Lines.Add('ping - '+IntToStr(a[CheckPing])+'ms');
  end;
except
  Memo1.Lines.Add('Не удалось соединится с сервером.');
  errors:=true;
end;
Маркъ вне форума Ответить с цитированием
Старый 24.09.2007, 14:28   #4
Квэнди
Старожил
 
Аватар для Квэнди
 
Регистрация: 13.12.2006
Сообщений: 3,859
По умолчанию

при пинге не удастся, программа будет "думать" до 5-и секунд, пока не получит ответ от удаленного хоста, можно попробовать использовать не Indy для пинга:
Вот известный пример в интернете:

type
IPINFO = record
Ttl: char;
Tos:har;
IPFlags: char;
OptSize: char;
Options: ^char;
end;




объявляем структурку для хранения ICMP пакета:


type
ICMPECHO = record
Source: longint;
Status: longint;
RTTime: longint;
DataSize: Shortint;
Reserved: Shortint;
pData: ^variant;
i_ipinfo: IPINFO;
end;




Объявляем функции и процедуры, которые мы будем вызывать из ICMP.DLL


TIcmpCreateFile = function():integer;
{$IFDEF WIN32} stdcall; {$ENDIF}

TIcmpCloseHandle = procedure(var handle: integer);
{$IFDEF WIN32} stdcall; {$ENDIF}

TIcmpSendEcho = function(var handle: integer; endereco: DWORD;
buffer: variant; tam: WORD; IP: IPINFO; ICMP: ICMPECHO;
tamicmp: DWORD; tempo: DWORD): DWORD;
{$IFDEF WIN32} stdcall; {$ENDIF}




В TButton в событие Onclick вставляем следующий код:


procedure TForm1.Button1Click(Sender: TObject);
var
wsadt : wsadata;
icmp :icmpecho;
HNDicmp : integer;
hndFile :integer;
Host :PHostEnt;
Destino :in_addr;
Endereco :^DWORD;
IP : ipinfo;
Retorno :integer;
dwRetorno :DWORD;
x :integer;

IcmpCreateFile : TIcmpCreateFile;
IcmpCloseHandle : TIcmpCloseHandle;
IcmpSendEcho : TIcmpSendEcho;

begin
if (edit1.Text = '') then
begin
Application.MessageBox('Enter a HostName ro a IP Adress', 'Error', MB_OK);
exit;
end;
HNDicmp := LoadLibrary('ICMP.DLL');
if (HNDicmp <> 0) then
begin
@IcmpCreateFile := GetProcAddress(HNDicmp,'IcmpCreateF ile');
@IcmpCloseHandle := GetProcAddress(HNDicmp,'IcmpCloseHa ndle');
@IcmpSendEcho := GetProcAddress(HNDicmp,'IcmpSendEch o');
if (@IcmpCreateFile=nil) or (@IcmpCloseHandle=nil) or (@IcmpSendEcho=nil) then
begin
Application.MessageBox('Error getting ICMP Adress’,'Error', MB_OK);
FreeLibrary(HNDicmp);
end;
end;
Retorno := WSAStartup($0101,wsadt);

if (Retorno <> 0) then
begin
Application.MessageBox('Canґt Load WinSockets','WSAStartup', MB_OK);
WSACleanup();
FreeLibrary(HNDicmp);
end;

Destino.S_addr := inet_addr(Pchar(Edit1.text));
if (Destino.S_addr = 0) then
Host := GetHostbyName(PChar(Edit1.text))
else
Host := GetHostbyAddr(@Destino,sizeof(in_ad dr), AF_INET);

if (host = nil) then
begin
Application.MessageBox('Host not found','Error', MB_OK);
WSACleanup();
FreeLibrary(HNDicmp);
exit;
end;
memo1.Lines.Add('Pinging ' + Edit1.text);

Endereco := @Host.h_addr_list;

HNDFile := IcmpCreateFile();
for x:= 0 to 4 do
begin
Ip.Ttl := char(255);
Ip.Tos := char(0);
Ip.IPFlags := char(0);
Ip.OptSize := char(0);
Ip.Options := nil;

dwRetorno := IcmpSendEcho(
HNDFile,
Endereco^,
null,
0,
Ip,
Icmp,
sizeof(Icmp),
DWORD(5000));
Destino.S_addr := icmp.source;
Memo1.Lines.Add('Ping ' + Edit1.text);
end;

IcmpCLoseHandle(HNDFile);
FreeLibrary(HNDicmp);
WSACleanup();
end;




У данного примера есть один недостаток - программа не воспримет доменное имя, только IP-адресс. Для пользователей NT не используйте функцию IcmpCloseHandle.
ICQ не для вопросов, а для предложений. Для вопросов используйте форум
IRC канал клуба программистов|Мои статьи
Квэнди вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Запуск программы на выполнение из другой программы. ViNcHeStEr Паскаль, Turbo Pascal, PascalABC.NET 6 18.06.2008 14:33
Две программы Манжосов Денис :) Софт 2 26.04.2008 12:29
программы koyot Фриланс 1 14.03.2008 13:10
"Подвисание" программы. skdon Работа с сетью в Delphi 6 18.11.2007 00:30
Программы Simply-Art Свободное общение 4 18.09.2007 22:41