Форум: "Сети";
Текущий архив: 2002.04.08;
Скачать: [xml.tar.bz2];
ВнизIndy.... Найти похожие ветки
← →
$hade (2002-01-21 14:22) [0]Народ! Я глючу или где?...
Есть сервер на TIdTCPServer (стандартный в D6)...Клиент соответственно TIdTCPClient....
Мне нужно получать сообщения от сервера...причем типа record.Для этого использую WriteBuffer/ReadBuffer...Вроде все нормально...Но так как у клиента нет события на пришедшее сообщение(или я плохо искал?)...приходится читать по таймеру... И тут косяк : Если буффер пустой (а проверить я это тоже не могу) то все виснет...Как это лечить?
← →
Digitman (2002-01-21 14:57) [1]Не может быть, чтобы класс TIdTCPClient не реализовал событие OnRead() ! И чтение буфера приема корректней всего выполнять в обработчике именно данного события (и неважно, Indy там или еще чего - суть работы синхронного режима гнезда одна и таже и не меняется ни в Indy ни где-то там еще : Winsock остается Winsock"ом). Если же ты читаешь буфер приема асинхронно (например, по таймеру), то возникающие ошибки - это только твои ошибки, а не Indy. Потому что чтение буфера приема гнезда, в принципе, допустимо в любом месте кода (при условии, что гнездо создано , инициализировано и соединено с гнездом-партнером по коннекту).
Приводи код - разберемся
← →
$hade (2002-01-21 15:37) [2]Ну нету там OnRead...нету! Есть OnStatus...вроде как возвращает состояние Read или Write...но опять же или я не разобрался или не работает...
а код...
OnTimer
if Client.connected then
if Client.CurrentReadBufferSize<>0 then
s:=Client.ReadString;// это чтение строки...примерно так..работает...
а вот так:
Client.ReadBuffer(Buff,SizeOf(Buff));
не работает - CurrentReadBufferSize всегда равен 0!
а если не делать проверку на размер...Client пытается прочитать буффер даже если там ничего нету...то есть сервер не отправлял ничего...((
← →
nikkie (2002-01-21 15:42) [3]зачем таймер? просто делаешь ReadBuffer (имхо CurrentReadBufferSize проверять не надо). Indy - блокирующие сокеты. если надо, чтобы приложение не подвисало - либо кидаешь на форму IdAntiFreeze, либо работаешь в отдельном потоке.
← →
$hade (2002-01-21 15:53) [4]Так а где его делать тогда (ReadBuffer) если не в таймере? как я узнаю что сообщение пришло?
...вот как раз когда не используешь CurrentReadBufferSize приложение и виснет...то есть как я понял пока он не прочитает SizeOf(Buff) он не успокоится...а прочитать не может потому что буффер пустой...((
← →
Digitman (2002-01-21 16:12) [5]а, ну , если Indy-клиент - блокирующий, тогда, разумеется, ввод-вывод синхронный д.б. (событий вв/выв гнезда в привычном VCL-виде там не будет)
← →
nikkie (2002-01-21 16:53) [6]ReadBuffer возвратит управление, когда придет столько данных, сколько ты просишь. какие проблемы?
виснет - не проблема. есть компонента AntiFreeze.
← →
$hade (2002-01-22 08:29) [7]все правильно...все работает...НО...КАК ОПРЕДЕЛИТЬ ЧТО ПРИШЛО СООБЩЕНИЕ??
← →
$hade (2002-01-22 08:32) [8]впрочем...мож кто подскажет какой-нить другой компонент в котором есть события OnRead/OnWrite + поддержка Proxy + SSL ?
← →
Digitman (2002-01-22 08:48) [9]var
FDSet: TFDSet;
TimeVal: TTimeVal;
BytesToRead: Longint;
...
FD_ZERO(FDSet);
FD_SET(IdTCPClient.SocketHandle, FDSet);
TimeVal.tv_sec := 0;
TimeVal.tv_usec := 500;
if (select(0, @FDSet, nil, nil, @TimeVal) > 0) then //FD_READ ?
begin
ioctlsocket(IdTCPClient.SocketHandle, FIONREAD, BytesToRead); // буфер чтения не пуст ?
if BytesToRead > 0 then
.... IdTCPClient.ReadBuffer(.., BytesToRead, ...); // можно читать не более BytesToRead байт
end;
единственное, в чем не уверен, это - наличие у IdTCPClient св-ва SocketHandle. Оно может и по-другому называться, но суть от этого не меняется : зная хэндл кл.гнезда, можно вот таким образом корректно обратиться к нему для чтения вх.буфера
← →
nikkie (2002-01-22 09:54) [10]>КАК ОПРЕДЕЛИТЬ ЧТО ПРИШЛО СООБЩЕНИЕ??
сработал оператор после ReadBuffer.
>другой компонент в котором есть события OnRead/OnWrite + поддержка Proxy + SSL ?
ты видно не понимаешь всей прелести. тебе НЕ НУЖНЫ эти события. событийное программирование сокетов - микрософтовская придумка. люди уже три десятка лет пишут сетевые программы без этих событий - и ничего.
почитай статью здесь:
http://www.hower.org/Kudzu/Articles/IntroToIndy/
может, понятней станет логика.
в indy есть поддержка SSL, есть поддержка socks. насколько я знаю, поддержки http-прокси нет, но ее можно сделать и самому, это должно быть не сложно - смотри RFC1945
← →
$hade (2002-01-22 10:06) [11]2nikkie ©
Thanks...обязательно почитаю...
но все-таки...вообще пишу чат( chat+InstantMessanger(ICQ)+IRC...вощем гибрид вcего :))..
надо как-то соображать что пришло сообщение/команда...(передается не только текст но и другие данные вплоть до картинки(баннер)-потому и передаю не текст а record)...
и не ждать когда наконец то прийдет сообщение от сервера чтоб отправить свое...
← →
nikkie (2002-01-22 10:17) [12]у тебя программа же не зависает? значит сообщения обрабатываются. значит и OnButtonClick сработает. там ты и делаешь отправку сообщения.
кроме того, можно сделать чтение в отдельном потоке. как данные пришли - синхронизируешься с основным потоком и отображаешь их.
← →
$hade (2002-01-22 12:26) [13]ну да...в принципе не зависает...потому как перерефрешивается...и все...не сдвинуть...не открыть/закрыть...:))
а потоки...можно конечно...но по моему это изврат...проще должно быть...))
← →
nikkie (2002-01-22 12:57) [14]блин... я действительно так непонятно объясняю? прочитай тогда статью.
компонента IdAntiFreeze с закладки Indy Misc.
а потоки - это вполне логичная вещь.
← →
$hade (2002-01-22 13:57) [15]2nikkie ©
да нет...все понятно...:) наверное я сам не непонятно выражаюсь... про AntiFreeze я знаю...
да ...наверное всетаки с потоками придется делать...)
Thanks 2All!
← →
nikkie (2002-01-22 14:28) [16]странно. а у тебя какая версия инди и дельфи? у меня дежа вю - вроде кто-то жаловался, что ReadBuffer вешает программу даже с антифризом. у меня D5 + Indy 8.00.23
смотри делаю так: новый апп, на форму кладу IdTCPClient, Host = "www.ya.ry", Port = 80.
кладу кнопку.
procedure TForm1.Button3Click(Sender: TObject);
var
buf : string;
begin
IdTCPClient1.Connect;
SetLength(buf, 10);
IdTCPClient1.ReadBuffer(buf[1], 10);
ShowMessage(buf);
end;
запускаю, нажимаю на кнопку - висит конкретно. понятное дело - я http запрос не отправил.
кладу антифриз, запускаю, нажимаю на кнопку - не висит.
кладу вторую кнопку
procedure TForm1.Button4Click(Sender: TObject);
begin
IdTCPClient1.Write("GET / HTTP 1.0"#13#10#13#10);
end;
запускаю, нажимаю на кнопку1, кнопку2 - получаю ответ.
но в любом случае с потоком лучше, я думаю.
← →
$hade (2002-01-24 15:30) [17]нее... AntiFreeze работает...
буду пробовать с потоками...
тут вот еще вопросы появились по ходу дела...))
1. OnWork,OnWorkBegin,OnWorkEnd - что ет за события и с чем их едят? :)
2. SendCmd, CheckForCmd... - что за команда (то есть как с етим работать...)
а в принципе хотелось бы найти доки и/или примерчики по использыванию Indy...
← →
nikkie (2002-01-24 16:47) [18]сайт инди http://www.nevrona.com/indy
там есть хелп, демо, статьи.
и хелп и демо, правда, обычно несколько отстают от актуальной версии.
с дельфи 6 идет версия 8.
← →
$hade (2002-01-24 17:03) [19]ага...я как раз забыл сказать что кроме Nevrona...я там ужо бывал...ничего нового почти не узнал..((
Страницы: 1 вся ветка
Форум: "Сети";
Текущий архив: 2002.04.08;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.006 c