Форум: "Сети";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 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...я там ужо бывал...ничего нового почти не узнал..((




Форум: "Сети";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.04.08;
Скачать: [xml.tar.bz2];




Наверх





Память: 0.76 MB
Время: 0.043 c
1-22671           Fredericco            2002-03-28 12:23  2002.04.08  
Вопрос, наверно, ламерский, но сам я его не решил.


1-22742           e-SiN                 2002-03-26 15:32  2002.04.08  
Always on Top


14-22815          Andrey                2002-02-27 12:41  2002.04.08  
Востановление файлов


1-22768           yar                   2002-03-27 11:59  2002.04.08  
FFT


1-22699           SPeter                2002-03-26 16:57  2002.04.08  
Как работать со свойством Shift:TShiftState.