Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

TspClient и TspServever [D7, XP]


Страницы:   1 2 3 4 5 6 7 8

kostyl_kostyl ©   (2009-08-12 12:38:00) 

Добрый день. Прошу показать пример обмена сообщениями сервера и клиента с помощью этих компонентов. У меня не выходит.
Я пишу:

procedure TForm1.TcpServer1Accept(Sender: TObject;
 ClientSocket: TCustomIpClient);
begin
 TcpServer1.Sendln('Ответ');
end;
//-----
 if TcpClient.Connect then
 begin
   TcpClient.Sendln('Запрос');
   Response := TcpClient.Receiveln;
   ShowMessage(Response);
 end
 else
   ShowMessage('Нет ответа');
 TcpClient.Disconnect;    

В лучшем случае  выдает пустую строку. В худшем зависает на Response := TcpClient.Receiveln;. Помогите разобраться.
Заранее благодарю.


Dennis I. Komarov   (2009-08-13 15:59:00) [61]


> Сделал вывод такой:

А надо другой:
Сперва определиться какого рода информация должна приходить от сервера.
Дальше от этого пляшем:
Спроектировать протокол обмена
Реализовать сервер.
И только после этого уже заниматься клиентской стороной...


Сергей М.   (2009-08-13 15:43:00) [62]


> Запускаю отдельные поток


Нахренаон нужен, если ты "снял блок" ?)
В неблок.режтиме все этго расчудесно реализуется в одном-единственном основном потоке.


kostyl_kostyl   (2009-08-13 15:35:00) [63]

Сделал вывод такой:
Снимаю блок чтобы никто не зависал
Стартую соединение
Посылаю данные
Запускаю отдельные поток
В цикле из 10 итераций со слипом в одну секунду пытаюсь принять данные.
Если принял отдаю их и как то убиваю соединение и поток. Если  по окончанию цикла убиваю соединение и поток и говорю что сервера нет.
Вопросы как убить поток из себя самого? Как понять что данные приняты? Не пропадут ли данные пока будет спать поток?


Сергей М.   (2009-08-13 12:28:00) [64]


> в bmNonBlocking можно хоть таймаут  сделать


Можно.
И в blocking тоже можно. Но при этом ты лишаешься преимущества использования функциональности метода ReceiveLn.


> Какие то не удачные компоненты


Нормальные компоненты.
Простые и понятные донельзя.
Может это у танцора проблемы ?)


kostyl_kostyl   (2009-08-13 12:14:00) [65]

Блин, все равно надо поток делать (а так не хочется еще и тут разбираться), но в bmNonBlocking можно хоть таймаут  сделать, как я понял... Какие то не удачные компоненты...


Сергей М.   (2009-08-13 11:59:00) [66]


> как будет вести себя клиент  в режиме bmNonBlocking ?


В этом режиме транспортные методы возвращают управление немедленно.

Пример для этого режима:
..

В обработчике OnError:

if SocketError <> WSAEWOULDBLOCK then TTCPClient(Sender).Disconnect;

...
ожидание и получение текстового сообщения от партнера-сервера, сервер в этом примере должен отправлять непустое сообщение, обязательно завершающееся CRLF:


ServerResponse := '';
while TCPClient.Connected and ServerResponse <> "" do begin
 ServerResponse := TCPClient.ReceveLn;
 Application.ProcessMessages;  // обработка потенциальных GUI-событий  
end;


Сергей М.   (2009-08-13 11:31:00) [67]


> как я понял самое простое решение сделать все в одном потоке
> в режиме клиента bmBlocking и наблюдать подвисания если
> сервер долго отвечает


Неправильно ты понял.

Как ты будешь "наблюдать", если у тебя всего одинпоток (основной) и он занят ожиданием ?

Решением для одного потока (основного) будет переход к bmNonBlocking.


kostyl_kostyl   (2009-08-13 11:21:00) [68]

Я наверно уже задолбал, но хочу спросит как будет вести себя клиент  в режиме bmNonBlocking ?
Заранее благодарю!


Dennis I. Komarov   (2009-08-13 11:15:00) [69]


> Короче, как я понял самое простое решение сделать все в
> одном потоке в режиме клиента bmBlocking и наблюдать подвисания
> если сервер долго отвечает. Но как быть если сервер будет
> очень долго записывать данные, тоесть он не до конца заполнит
> строку и зависнет полностью. Тогда и приложение всё зависнет.
>  Есть какие то таймауты или чтото такое?

Вынеси в дополнительный поток...


kostyl_kostyl   (2009-08-13 11:11:00) [70]

Короче, как я понял самое простое решение сделать все в одном потоке в режиме клиента bmBlocking и наблюдать подвисания если сервер долго отвечает. Но как быть если сервер будет очень долго записывать данные, тоесть он не до конца заполнит строку и зависнет полностью. Тогда и приложение всё зависнет. Есть какие то таймауты или чтото такое?


Сергей М.   (2009-08-13 10:58:00) [71]


> какой тип исключения


Пардон, наврал я тебе.
Не исключение генерируется, а вызывается обработчик OnError, коему параметром передается конкретный код причины отказа. (см. WSAGetLastError)


Сергей М.   (2009-08-13 10:55:00) [72]


> как же тогда клиент может разорвать соединение если он ожидает
> конца строки в методе Receive?


Из другого потока закрыв хэндл сокета.
При этом блокирующее выполнение метода завершится с исключением.


kostyl_kostyl   (2009-08-13 10:50:00) [73]

Теперь все становится понятным. Спасибо за подробное объяснение.

> но с возбуждением исключения

А какой тип исключения не подскажите?
Постойте-ка, а как же тогда клиент может разорвать соединение если он ожидает конца строки в методе Receive?


Сергей М.   (2009-08-13 10:31:00) [74]


> в режима bmBlocking клиент будет ждать пока сервер не отправит
> ему данные?


В этом режиме клиент вызвав ReceiveLn ждет до тех пор пока не получит строку целиком.
Если в ходе ожидания соединение будет разорвано (по инициативе сервера или по иной не зависящей от клиента причине), Receive-метод также завершит выполнение, но с возбуждением исключения.


> как тогда он поймет, что все данные отправлены?


Клиенту нет дела до отправки, он заинтересован в получениитого что он ожидает.
Если клиент ожидал некую строку (по умолчанию концом строки клиент считает символы CRLF) и эта строка была успешно доставлена, то Receive-метод вернет управление, возвратив полученную строку.


kostyl_kostyl   (2009-08-13 10:18:00) [75]


> В VCL-приложении - основной.

Ну я так и думал в принципе. Вы хотите сказать, что в режима bmBlocking клиент будет ждать пока сервер не отправит ему данные? А как тогда он поймет, что все данные отправлены?


Сергей М.   (2009-08-13 08:13:00) [76]

В VCL-приложении - основной.
И он же, основной поток, у тебя вызывает метод ReceiveLn.
Пока метод не завершит выполнение, осн.поток не будет исполнять свои GUI-обязанности, что и создает иллюзию "подвисания".
Отсюда напрашивается решение: либо переносить работу с TTCPClient в доп.поток (он так же будет "зависать" на время вызова метода, но это не повлияет на работу осн.потока, ибо потоки исполняются "параллельно") либо переводить TTCPClient в режим bmNonBlocking, оставив работу с ним в осн.потоке.


kostyl_kostyl   (2009-08-12 22:17:00) [77]

Если честно не в курсе


Сергей М.   (2009-08-12 20:22:00) [78]

А ты вообще в курсе, какой кодовый поток процесса твоего приложения ответственен за GUI ?


kostyl_kostyl   (2009-08-12 20:02:00) [79]

Я не знаю как будет на самом деле, но знаю что сервер точно сформирует ответ. А вот когда это будет я без понятия, возможно я уже отконнекчусь и он не успеет передать данные. Значит мне надо подождать пока он это сделает, но вот ждать я не могу. Что делать? Может сделать обработку ответа в отдельном потоке, а по приходу ответа изменить какую то глобальную переменную и запусить ProcessServerResponse(ServerResponse)?


kostyl_kostyl   (2009-08-12 18:33:00) [80]

Постараюсь лучше объяснить:
Вот у меня код обработки ответа:

1.  TcpClient.SendBuf(ClientRequest, 13);
2.  TcpClient.ReceiveBuf(ServerResponse, 268);
3.  TcpClient.Disconnect;
4.  ProcessServerResponse(ServerResponse);

Меня смущает что строки 1 и 2 выполняться в один момент и вижу два бока, когда либо клиент зависнет на строке 2 либо в строке 4 ServerResponse будет неверная информация, потому что сервер долго обрабатывает запрос.


Страницы:   1 2 3 4 5 6 7 8

Наверх

Титульная страница Поиск, карта сайта Написать письмо