Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2003.12.16;
Скачать: [xml.tar.bz2];

Вниз

Глупый вопрос по TTCPClient   Найти похожие ветки 

 
alt7   (2003-10-21 14:26) [0]

Не могу понять вот какой вещи.

С помощью данного компонента коннекчусь к серверу, прохожу авторизацию и подписываюсь на определенные порции данных, пользуюсь методами ReceiveLn, SendLn, SendBuf. Это все в отдельной процедуре.

Затем эти данные ничанают сыпаться моему клиенту, НО обработчик TTCPClient.OnReceive не срабатывает, когда они приходят, почему?

Обходной путь, сделал таймер который срабатывает 10 раз в секунду, а в нем вызываю ReceiveLn для компонента, но это грузит процессор на все 100% и не подходит мне.

Главные вопросы: почему не срабатывает событие OnReceive, и что сделать, чтобы срабатывало без вышеупомянутого таймера?


 
Reindeer Moss Eater   (2003-10-21 15:45) [1]

Главные ответы:
Событий никаких не нужно, так же как и таймера.
Все методы синхронные вызвал - получил по возврату из вызова


 
alt7   (2003-10-21 15:57) [2]

Гм, то есть ты хочешь сказать, что пока я не сделаю ReceiveLn, то сервер мне ничего не ответит? А мне ведь надо, чтобы я один раз подписался на нужные данные, а сервер по мере появления данных у него, отсылал мне эти данные постоянно, пока я законнекчен... (не очень сумбурно? ;)))

То есть именно нужен обработчик, который постоянно бы мог обрабатывать поступающую инфо без всяких ReceiveLn, SendLn...

Если этого не может TTCPClient, то чем можно такое сделать?


 
Reindeer Moss Eater   (2003-10-21 16:00) [3]

Я про сервер ни слова не сказал.
Я сказал, что для получения данных нужно вызвать метод.
Как только произойдет возврат из метода - данные пришли или случился таймаут.


 
Reindeer Moss Eater   (2003-10-21 16:07) [4]

Кстати, что такое TTCPClient?


 
alt7   (2003-10-21 16:13) [5]

1) Ну вот видишь меня так не устраивает, данные получаю критичные, секунда имеет огромную важность.
Посему такой вопрос, куда и как можно впихнуть ReceiveLn (я правильно тебя понял?) чтобы обработать новую порцию данных? И чтобы при этом не грузить проц на 100%.

2) Deplhi 7, выдержка из Help

TTcpClient is the TCP client component

Unit

Sockets

Description

Use TTcpClient to create TCP client applications.

TTcpClient publishes properties and events from its ancestor socket components.


 
Reindeer Moss Eater   (2003-10-21 16:16) [6]

Ну вот видишь меня так не устраивает, данные получаю критичные, секунда имеет огромную важность.

1. Синхронный режим этому никак не мешает.
2. Мы про разные классы разговаривали. Так что забудь.


 
alt7   (2003-10-21 16:26) [7]

Хорошо, тогда подсоби все же если можешь с решением вопроса:

Если не TTCPClient, то в каком классе можно так: при поступлении данных срабатывает некоторое событие (без вызова ReceiveLn) и в его обработчике я уже буду писать свой код.

Если такого нельзя, то куда и как поместить вызов ReceiveLn, чтобы не грузить процессор на 100%?


 
Reindeer Moss Eater   (2003-10-21 16:31) [8]

при поступлении данных срабатывает некоторое событие (без вызова ReceiveLn)

Ты думаешь, что событие в каком-то классе - это результат активности сервера на другом конце?
Это всего навсего код создателя класса который внутри класса читает данные (а делает он это потому что пользователь класса вызвал метод класса заставляющий класс выполнить чтение даных).

Иными словами, что бы иметь события - необхродимо вызывать методы.


 
alt7   (2003-10-21 16:38) [9]

Здесь все понятно, спасибо за разъяснение ;))

Зайдем с другого конца:
Коннекчусь я телнетом к тому же серваку, подписываюсь на данные, даю команду серваку, и он мне начинает сыпать данные, хоть минуту, хоть час, хоть месяц...
А я ведь не пишу каждую минуту, час, месяц - ReceiveLn, я просто сижу, а они сыпятся.

Так вот мне такое и на Делфи сделать, чтобы я дал команду, а сервер мне хоть месяц все сыпал и сыпал без каких-либо моих команд в течении этого месяца.


 
Reindeer Moss Eater   (2003-10-21 16:41) [10]

А я ведь не пишу каждую минуту, час, месяц - ReceiveLn, я просто сижу, а они сыпятся.

А какая связь между " Я НИЧЕГО НЕ ПИШУ ТЕЛНЕТ СЕРВЕРУ" и "Телнет клиент читает сообщения которые пишет телнет-сервер" ?


 
alt7   (2003-10-21 17:22) [11]

Так ведь ты же пишешь, что для того чтобы что-то получить клиентом нужно вызвать соответствующий метод класса, к примеру ReceiveLn. а если мне ПОСТОЯННО надо что-то читать от телнет-сервера, и нет никакой переодичности в поступлении сообщений, мне же приходится постоянно вызывать ReceiveLn или же делать проверку WaitForData с таймаутом, чтобы узнать, что что-то пришло. Но вся шутка в том что ПОСТОЯННО, постоянно я придумал только по таймеру, и получается что грузим проц на 100%. Вот как бы обойти это дело...


 
Reindeer Moss Eater   (2003-10-21 17:28) [12]

Тут тоже никакого волшебства нет.
Вызовешь метод чтения строки, получишь от сервера строку - и снова вызывай метод чтения строки (строка для примера).
Либо один раз метод чтения буфера длинны N.
Обрабатывай буфер (ищи разделители строк) и отображай результат


 
alt7   (2003-10-21 17:33) [13]

1) Размер буфера, а точнее количество байтов я зараннее не знаю, можно ли указать какое-нить большое число, и чтоб не было ошибки?

2)
> Вызовешь метод чтения строки, получишь от сервера строку
> - и снова вызывай метод чтения строки


И где вызывать этот метод? Учитывай же, что мне придется постоянно его вызывать, потому как время поступления мне критически важно.


 
Rouse_   (2003-10-21 17:35) [14]

Без кода вы опускаетесь до бесполезного флейма и разговариваете о разных вещах.

> alt7
Покажи свой код, и тебе скажут где ошибка
(ну это помимо ошибки в 17-ой строке наличествующей сейчас).

Желаю успехов


 
alt7   (2003-10-21 17:48) [15]

Порезал немного для краткости. Команда STAR - сервер начинает отсылать данные.


procedure EventClass.Before_get_quote;
var
zz: Integer;
USR,REQU,START: String;
REQU_arr: Array[1..9] of String;
begin
USR := <skipped>;
REQU := <skipped>
<skipped заполненние массива REQU>

while true do
try
if Form_CTD.TCPCClient.WaitForData(10) then break;
except on ESocketError do begin WriteLn(vLogFile,"Connection error. Trying to reconnect... ("+DateTimeToStr(Now)+")"); Before_get_quote; exit; end; end;
Buffer := Form_CTD.TCPCClient.Receiveln;
if Pos(cOKString,Buffer) <> 0 then
begin
Form_CTD.TCPCClient.Sendln(USR);
end;
while true do
try
if Form_CTD.TCPCClient.WaitForData(10) then break;
except on ESocketError do begin WriteLn(vLogFile,"Connection error. Trying to reconnect... ("+DateTimeToStr(Now)+")"); Before_get_quote; exit; end; end;
Buffer := Form_CTD.TCPCClient.Receiveln;
if Pos("OK User logged ",Buffer) <> 0 then
begin
for zz := 1 to Length(REQU) do
begin
SendChar := REQU[zz];
Form_CTD.TCPCClient.SendBuf(SendChar,1,0);
end;
Form_CTD.TCPCClient.SendLn("");
for zz := 1 to Length(REQU_arr[1]) do
begin
SendChar := REQU_arr[1][zz];
Form_CTD.TCPCClient.SendBuf(SendChar,1,0);
end;
Form_CTD.TCPCClient.SendLn("");
<skipped однотипно>
end;

while true do
try
if Form_CTD.TCPCClient.WaitForData(10) then break;
except on ESocketError do begin WriteLn(vLogFile,"Connection error. Trying to reconnect... ("+DateTimeToStr(Now)+")"); Before_get_quote; exit; end; end;
Buffer := Form_CTD.TCPCClient.Receiveln;
if (Pos("OK",Buffer) <> 0) and (Length(Buffer) = 2) then
begin
for zz := 1 to Length(STAR) do
Form_CTD.TCPCClient.SendBuf(STAR[zz],1,0);
Form_CTD.TCPCClient.SendLn("");
end;
end;


Далее сервер мне сыпет данные, которые я должен обрабатывать.
Мои вопросы по этому делу можно прочитать выше...


 
alt7   (2003-10-21 18:09) [16]

Видать завуалированный исходник ;))

У меня ведь все же вопрос более теоритический ;))

Если мне надо постоянно вызывать WaitForData или ReceiveLn, то с использованием таймера, грузим проц на 100%. Как это обойти?


 
Rouse_   (2003-10-22 09:31) [17]

Вопервых не вижу код который отвечает за прием данных от сервера, когда он начинает "Сыпать данными". Скорее ошибка в нем...

Второе, не буду ничего говорить про стиль написания, но вот этот момент мне не понятен:
for zz := 1 to Length(REQU) do
begin
SendChar := REQU[zz];
Form_CTD.TCPCClient.SendBuf(SendChar,1,0);
end;


А почему не весь буфер сразу отсылать?

Ну и еще:
> if (Pos("OK",Buffer) <> 0) and (Length(Buffer) = 2) then
Не кажется что будет проще: if Buffer = "OK" then ...

Желаю успехов


 
alt7   (2003-10-22 11:34) [18]

По пунктам:

1) Кода нет, потому как я не знаю куда его пихать, про это я уже много выше говорил, про OnReceive, таймер и иже с ними.

2) Приходится так, потому что сервер почему-то говорит BAD, а не OK, если весь буфер отсылать (сервер не наш).

3) Это просто перенесенный кусок из старого приложения, окончательную доводку и гм, оптимизацию кода еще рано делать.

Тут вот еще вопрос возник. Клиент работает в блокирующем режиме, сервер - не знаю в каком. Возможно ли, что если поставить клиенту асинхронный, то станет срабатывать событие OnReceive. Если я счас бред сказал, не пинайте - просто скажите ;))


 
Rouse_   (2003-10-22 12:01) [19]

Ааа, так сервер не твой? Если так то попробуй для начала приема данных посылать #13#10.

Желаю успехов


 
Rouse_   (2003-10-22 12:09) [20]

Точнее я не правильно выразился.
К примеру ты коннектишся на РОР3-сервер.
Ты должен посылать в конце каждой комманды #13#10. (Т.е. буффер который ты посылаешь должен завершаться этими двумя кодами - перевод строки и возврат каретки)
К примеру:
user Rouse#13#10
+ OK
pass MyPassword#13#10
+ OK
stat#13#10
после этой комманды тебе и пойдет ответ

Желаю успехов

ЗЫ: Если я правильно понял о чем речь


 
alt7   (2003-10-22 12:17) [21]

А смысл?

Ведь авторизацию я прохожу, подписываюсь, на все это сервер отвечает ОК.

Если я включаю свой таймер, то данные принимаются, и я в OnReceive могу их обработать.

В OnTimer пишу Form_CTD.TTCPCClient.ReceiveLn;

А вот без этого постоянного срабатывания OnTimer, то бишь без постоянного ReceiveLn, OnReceive не срабатывает, и я не могу обработать поступающие данные.


 
Rouse_   (2003-10-22 12:22) [22]

А смысл в RFC. Это стандарт. Ты вначале попробуй, а потом скажешь, получилось или нет.

Желаю успехов


 
alt7   (2003-10-22 12:44) [23]

Так не работает, я даже авторизацию не могу пройти, вместо #13#10 я везде писал SendLN, и с ним работало


 
Rouse_   (2003-10-22 13:33) [24]

Что за сервер?


 
alt7   (2003-10-22 13:33) [25]

К сожалению не могу сказать IP-шник, коммерческая тайна ;))
Серьезно.


 
Rouse_   (2003-10-22 13:35) [26]

Я имею ввиду FTP, SMTP, POP3?


 
alt7   (2003-10-22 13:37) [27]

Telnet


 
Rouse_   (2003-10-22 13:41) [28]

А есть возможность узнать и сравнить какие данные отсылаются и приходят к нему?


 
alt7   (2003-10-22 13:50) [29]

Что-то вопроса я не понял...
То что я отсылаю серверу, то к ниму и приходит, а как же иначе?

Ничего ж не меняется все мои команды работают прекрасно.


 
Rouse_   (2003-10-22 13:56) [30]

Хм, у меня почемуто есть уверенность что вы отправляете всеже не то что вы думаете... Попробуйте писать в лог все данные которые отправлены и смотреть. Т.е. ушла строка в сеть, этуже строку без искажений в файл. Ушол элемент из буфера егоже в файл. И желательно сравнить как они приходят данные на сервер. Может быть еще проблема с асинхронностью.

Короче много вариантов. Вечером если не забуду постараюсь кинуть код.


 
alt7   (2003-10-22 14:01) [31]

Сомневаюсь. Обоснования:

Если я включаю таймер - логинюсь, подписываюсь на данные, даю команду STAR - сервер начинает передавать мне данные. OnReceive работает, вообщем если бы только не было загрузки проца на 100% - все было бы прекрасно.

Таймер выключаю - все, OnReceive не работает.

То есть, мои команды в порядке, отсылаю я их правильно, и сервер получает их правильно. Проблема на стороне клиента, а не сервера.
Клиент в BlockingMode. Насчет лога, сделаю сейчас - посмотрю, но очень сомневаюсь...

Спасибо..


 
Rouse_   (2003-10-22 14:04) [32]

Если срабатывает самое первое OnReceive то можно в конце приема сделать Receiveln; По идее должно по приходу данных опять отработать OnReceive. Это чтобы небыло зависимости от таймера.


 
alt7   (2003-10-22 14:40) [33]

Сделал, работаем без таймера...
Но тут беда видимо попроще ;))

Загрузка проца в норме, 1-3%...

На форме у меня TMemo и я вижу по нему, что данные приходят.. вот только не могу за заголовок подвигать к примеру..

Кажется Application.ProcessMessages надо куда-то положить, вопрос куда? Чтобы я мог нормально подвигать, или закрыть приложение...


 
Rouse_   (2003-10-22 14:59) [34]

В OnReceive

Желаю успехов

ЗЫ: Так последний совет всеже помог?


 
Erik   (2003-10-22 15:00) [35]

Блин ну и бодягу вы здесь развели.
alt7
Ты что такое TThread знаеш? Надеюсь, что знаеш вот его и используй. В нем читай в цикле приходящей буфер хотябы на 20 байт или сколько у тебя обычно приходит. Пока непрочитаеш висиш на этой строчке, после опять на нео поподеш. В томже цикле уведоми основной поток, что данные пришли!
Лично я если надо было, чтото просто сделать использовал Indy. Там есть твои любимае события, только используй UDP а то будеш спрашивать как приходящие данные склеивать. И посылай пакетами.



Страницы: 1 вся ветка

Форум: "Сети";
Текущий архив: 2003.12.16;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.01 c
1-52142
Mishenka
2003-12-03 20:50
2003.12.16
Запуск файла из проги???


4-52449
Serg
2003-10-22 21:29
2003.12.16
Подскажите пожалуйста как...


14-52334
Kair
2003-11-19 07:42
2003.12.16
Управление с помощью компьютера


1-52202
DVP777
2003-12-05 11:24
2003.12.16
Автоповтор в проигрывания в MediaPlayer? - ну, забыл ей-богу!


3-52084
chtr
2003-11-24 16:01
2003.12.16
Подскажите фишку:





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский