Мастера DELPHI, Delphi programming community Рейтинг@Mail.ru Титульная страница Поиск, карта сайта Написать письмо 
| Новости |
Новости сайта
Поиск |
Поиск по лучшим сайтам о Delphi
FAQ |
Огромная база часто задаваемых вопросов и, конечно же, ответы к ним ;)
Статьи |
Подборка статей на самые разные темы. Все о DELPHI
Книги |
Новинки книжного рынка
Новости VCL
Обзор свежих компонент со всего мира, по-русски!
|
| Форумы
Здесь вы можете задать свой вопрос и наверняка получите ответ
| ЧАТ |
Место для общения :)
Орешник |
Коллекция курьезных вопросов из форумов
KOL и MCK |
KOL и MCK - Компактные программы на Delphi
Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / rsdn.org

 
Чтобы не потерять эту дискуссию, сделайте закладку « предыдущая ветвь | форум | следующая ветвь »

TServerClientThread.ClientExecute; подскажите дубу как правильно?


kashey ©   (25.10.18 15:37

unit serverthread;

interface

uses
 windows, scktcomp, SysUtils, Classes, Forms;

type
 EServerThread = class( Exception );
 // serverthread это потомок TServerClientThread
 TServerThread = class( TServerClientThread )
   private
     fSocketStream : TWinSocketStream;
   public
     procedure ClientExecute; override;
     // ClientExecute отменяет
     // TServerClientThread.ClientExecute
     // и содержит код, который
     // выполняется при старте потока
 end;

implementation

procedure TServerThread.ClientExecute;
var
 RStr: String;
 TotalStr: String;
begin
 TotalStr := '';
 inherited FreeOnTerminate := TRUE;
 try
   fSocketStream := TWinSocketStream.Create( ClientSocket,
                                             100000 );
   // 100000 - это таймаут в миллисекундах.
   try
     while ( not Terminated ) and ( ClientSocket.Connected ) do
     try
       // Тут я читаю данные от клиента
       // Данные могут быть большой длинны, поэтому
       // ответ от клиента приходит несколькими порциями
       // Читаю так:
        FRecvSize:= ClientSocket.ReceiveLength;
        SetString(RStr, PAnsiChar(@FBuffer[0]), FRecvSize);
       
       //по кускам все прекрасно выводится
       //ShowMessage(RStr);
       //А вот собрать в одну переменную и передать дальше в параметром
       //в функцию не получается
       TotalStr :=  TotalStr + RStr; ????
   
       //Видать что-то с доступом с разных потоков связано?
       //ПОДСКАЖИТЕ ПРАВИЛЬНУЮ РЕАЛИЗАЦИЮ.
     except on e:exception do
       begin
         ClientSocket.Close;
         Terminate;
       end;
     end;
   finally
     fSocketStream.Free;
   end;
 except on e:exception do
   begin
     ClientSocket.Close;
     Terminate;
   end;
 end;
end;


Eraser ©   (26.10.18 01:03[1]


> kashey ©   (25.10.18 15:37) 

не используй эти компоненты. они глючные, устаревшие и не кроссплатформенные.
см. Indy.


Германн ©   (26.10.18 02:21[2]


> Eraser ©   (26.10.18 01:03) [1]
>
>
> > kashey ©   (25.10.18 15:37)
>
> не используй эти компоненты. они глючные

Имхо они просто куплены были папашей Борландом на случайном рынке. Покупка была явно неудачной тратой пяти копеек. :)


kashey ©   (26.10.18 08:22[3]

Кажись разобрался с логикой работы этого "безобразия". Получается создается отдельный поток и цикл while ( not Terminated ) and ( ClientSocket.Connected ) do работает вечно слушая клиента. И понять все ли тебя прислал клиент или какую-то часть невозможно никак, если нет никакого признака начала и конца данных, а их и нет. Поэтому единственный вариант это определить пришедшие данные по внешнему виду, например если это XML, то просто проверить на валидность хотя бы так:
try
 XML.add(RecvPart)
 XML.Activ := True
 //действия
 XML.Clear;
except

end;

Мне собственно XML и присылают. Вобщем все со скрипом заработало.


> не используй эти компоненты. они глючные, устаревшие и не
> кроссплатформенные.
> см. Indy.


Вы серьёзно? На другом форуме подсказали выкинуть Indy и использовать это) Я никогда и близко с сетью не работал и потому поверил:)))

И опять же в Indy10 OnExecute будет крутится вечно, поэтому логика будет та же. А в Indy9 такого не было(наверное работал в основном потоке), OnExecute - заканчивал работу и в конце этого события можно было забрать все данные. У вас кстати есть по этому поводу похожая тема http://www.delphimaster.ru/cgi-bin/forum.pl?id=1539978759&n=18


KSergey ©   (26.10.18 09:03[4]

> kashey ©   (26.10.18 08:22) [3]
> И понять все ли тебя прислал клиент или какую-то часть невозможно никак, если нет никакого признака начала
> и конца данных, а их и нет. Поэтому единственный вариант это определить пришедшие данные по внешнему виду, например
> если это XML, то просто проверить на валидность

А это не зависит от используемых компонент и/или API.

Это суть работы через сеть, которые я бы описал двумя базовыми принципами:
- нет признака "достигнут конец данных", "в сети более ничего нет и не будет" по аналогии с "достигнут конец файла"; такой признак следует передавать явно каким-то образом в данных;
- на клиента данные будут приезжать кусками произвольного размера, разрезанные в любом произвольном месте; нельзя ожидать и нельзя закладываться в алгоритме обработки на клиенте, что будут приходить целиком строки или целиком другие осмысленные куски или куски какого-то (минимального) размера; клиент будет получать всё кусочками произвольного размера, разного размера: 1 байт, три байта, 1039 байт, 126 байт, 4091 байт и т.д.; алгоритм обработки данных на клиенте должен быть готов к такому.

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


kashey ©   (26.10.18 09:21[5]


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

Я с этим столкнулся неделю назад, и ждал прямой логики (что послал, то и получил в целом и полном виде).


kashey ©   (26.10.18 10:41[6]

Серьёзно вы меня озадачили информации о глючности этих компонент. Хотя работает пока нормально. Но всёж пробую запасной вариант на Indy.
Чтение данный от клиента адаптировал в TidTCPServer, а вот как послать данные с него клиенту не получается.

с глючных компонент слал так:
procedure TMyServer.SendCommand(const Cmd: string; ConnNo: Integer);
begin
 {TServerSocket}
 FServerSocket.Socket.Connections[ConnNo].SendText(Cmd + #0);
end;


Реализация клиента не доступна и соответственно как он обрабатывает данные тоже не известно
но работало по варианту выше.

а вот эквивалент на Indy этой процедуре не найду.

ib: TIdBytes;

Cmd := 'my command' + #0;
SetLength(ib, Length(Cmd));
Move(Cmd[1],ib[0],Length(Cmd));
AContext.Connection.IOHandler.Write(ib);


пробовал и в  начало ib писать длинну команды в байтах, хотя по идее она должна обрабатывать клиентом признаком конца строки как тут:
FServerSocket.Socket.Connections[ConnNo].SendText(Cmd + #0);


kashey ©   (26.10.18 11:50[7]


> а вот эквивалент на Indy этой процедуре не найду.

Извиняюсь, достаточно слать сразу строку
AContext.Connection.IOHandler.Write(Str);
и AContext.Connection.IOHandler.InputBuffer до конца не дочитовал с прошлой команды и привет - все сыпалось при новом чтении.

И коду в 5 раз меньше на Indy стало, так серьезно от тех компонент лучше отказаться?


Германн ©   (30.10.18 01:52[8]


> KSergey ©   (26.10.18 09:03) [4]

> Удивительно, кстати, что ни в одной книжке про работу с
> сетью лично мне вот этого написанного в явном виде - не
> попадалось.

Насчёт книжек сказать ничего не могу. Но Франсуа Пиетт (автор ICS) в своих публикациях это упоминал часто. Возможно именно потому, что он работал с сетью наиболее родным способом. Т.е. асинхронным.
Добавлю что я уже много лет убеждаю новичков, которые работают с СОМ-портом, что драйвер компорта отнюдь не обязан отдавать им всё и сразу. И это тоже не описано в книжках.


версия для печати

Написать ответ

Ваше имя (регистрация  E-mail 







Разрешается использование тегов форматирования текста:
<b>жирный</b> <i>наклонный</i> <u>подчеркнутый</u>,
а для выделения текста программ, используйте <code> ... </code>
и не забывайте закрывать теги! </b></i></u></code> :)


Наверх

  Рейтинг@Mail.ru     Титульная страница Поиск, карта сайта Написать письмо