-
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;
-
> kashey © (25.10.18 15:37)
не используй эти компоненты. они глючные, устаревшие и не кроссплатформенные. см. Indy.
-
> Eraser © (26.10.18 01:03) [1] > > > > kashey © (25.10.18 15:37) > > не используй эти компоненты. они глючные
Имхо они просто куплены были папашей Борландом на случайном рынке. Покупка была явно неудачной тратой пяти копеек. :)
-
Кажись разобрался с логикой работы этого "безобразия". Получается создается отдельный поток и цикл 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://pda.delphimaster.net/?id=1539978759&n=18
-
> kashey © (26.10.18 08:22) [3] > И понять все ли тебя прислал клиент или какую-то часть невозможно никак, если нет никакого признака начала > и конца данных, а их и нет. Поэтому единственный вариант это определить пришедшие данные по внешнему виду, например > если это XML, то просто проверить на валидность
А это не зависит от используемых компонент и/или API.
Это суть работы через сеть, которые я бы описал двумя базовыми принципами: - нет признака "достигнут конец данных", "в сети более ничего нет и не будет" по аналогии с "достигнут конец файла"; такой признак следует передавать явно каким-то образом в данных; - на клиента данные будут приезжать кусками произвольного размера, разрезанные в любом произвольном месте; нельзя ожидать и нельзя закладываться в алгоритме обработки на клиенте, что будут приходить целиком строки или целиком другие осмысленные куски или куски какого-то (минимального) размера; клиент будет получать всё кусочками произвольного размера, разного размера: 1 байт, три байта, 1039 байт, 126 байт, 4091 байт и т.д.; алгоритм обработки данных на клиенте должен быть готов к такому.
Удивительно, кстати, что ни в одной книжке про работу с сетью лично мне вот этого написанного в явном виде - не попадалось. Хотя это база и суть в подходах организации логики сетевых приложений. И это первое, обо что ударяешься и долго не можешь понять. Принять это тоже не сразу удаётся, кстати.
-
> Удивительно, кстати, что ни в одной книжке про работу с > сетью лично мне вот этого написанного в явном виде - не > попадалось. Хотя это база и суть в подходах организации > логики сетевых приложений. И это первое, обо что ударяешься > и долго не можешь понять. Принять это тоже не сразу удаётся, > кстати.
Я с этим столкнулся неделю назад, и ждал прямой логики (что послал, то и получил в целом и полном виде).
-
Серьёзно вы меня озадачили информации о глючности этих компонент. Хотя работает пока нормально. Но всёж пробую запасной вариант на Indy. Чтение данный от клиента адаптировал в TidTCPServer, а вот как послать данные с него клиенту не получается. с глючных компонент слал так: procedure TMyServer.SendCommand(const Cmd: string; ConnNo: Integer);
begin
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);
-
> а вот эквивалент на Indy этой процедуре не найду.
Извиняюсь, достаточно слать сразу строку AContext.Connection.IOHandler.Write(Str); и AContext.Connection.IOHandler.InputBuffer до конца не дочитовал с прошлой команды и привет - все сыпалось при новом чтении.
И коду в 5 раз меньше на Indy стало, так серьезно от тех компонент лучше отказаться?
-
> KSergey © (26.10.18 09:03) [4]
> Удивительно, кстати, что ни в одной книжке про работу с > сетью лично мне вот этого написанного в явном виде - не > попадалось.
Насчёт книжек сказать ничего не могу. Но Франсуа Пиетт (автор ICS) в своих публикациях это упоминал часто. Возможно именно потому, что он работал с сетью наиболее родным способом. Т.е. асинхронным. Добавлю что я уже много лет убеждаю новичков, которые работают с СОМ-портом, что драйвер компорта отнюдь не обязан отдавать им всё и сразу. И это тоже не описано в книжках.
|