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

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

O пересылке данных с TIdTCPServer [D7, WinXP]


Страницы:   1 2

DanilinS ©   (2006-07-25 15:15:00) 

Необходимо дергать данные с сервера. Данные структурированы но их обьем заренее не известен.

Не могу понять, почему не работает следующий код:

Сервер:

код:
procedure TForm1.CommandServerException(AThread: TIdPeerThread;
 AException: Exception);
var
 TempStrings: TStrings;
 I:Byte;
begin
 AThread.Connection.ReadBuffer(CommandS, SizeOf(CommandS));
 case CommandS.Command of
   01: begin  // старт динамического импорта

      ...
       end;
   02: begin     // Стоп динамического импорта
          ...
       end;
   03: begin     // Запрос перечня данных
         if PathBase = '' then Exit;
         if PathBase[Length( PathBase )] <> '\' then
           PathBase := PathBase + '\';
         FillSymbols(PathBase);  // загнали данные в массив
         TempStrings:=TStringList.Create;
         For i:=0 to Length (ArrayMasterRec) do
           TempStrings.Add(ArrayMasterRec[i].Name);
         Label3.Caption:= ArrayMasterRec[0].Name;
         AThread.Connection.WriteStrings(TempStrings); // кинули данные
         TempStrings.Free;
       end;
   04: begin   // Запрос исторических данных
          ...
       end;
 end;
end;


клиент:
код:
procedure TForm1.Button3Click(Sender: TObject);
var
 TempList: Tstrings;
 Int: integer;
 S: string;
begin
 TempList := TStringList.Create;
 CommandS.Command:=3;
 IdTCPClient1.Connect(-1);
 IdTCPClient1.WriteBuffer(CommandS, SizeOf(CommandS));
 Int:=IdTCPClient1.ReadInteger(true);
 IdTCPClient1.ReadStrings(TempList);  <- получаю "Connection Closed Gracefully"
 Memo1.Lines.AddStrings(TempList);
 IdTCPClient1.Disconnect;
 TempList.Free;
end;


Кто подскажет, как TString через сетку протащить?


Сергей М.   (2006-08-11 15:41:00) [1]


> Какой Stream нужно в этом случае использовать? (TMemoryStream
> ?)


Любой наследник TStream


DanilinS   (2006-08-11 15:35:00) [2]

В догонку вопрос:
Если на стороне сервера (TIdTCPServer) используеться функция AThread.Connection.WriteFile
то какой функцией TIdTCPClient эти данные можно принять "оптом" (не по байтно)?

функцией IdTCPClient1.ReadStream ? Какой Stream нужно в этом случае использовать? (TMemoryStream ?)


Сергей М.   (2006-07-26 12:23:00) [3]

В условиях глоб.сети твой код может споткнуться еще об одни грабли.
Посмотри внимательно на ф-цию Get/SetSockOpt и опции SO_LINGER/SO_DONTLINGER.


DanilinS   (2006-07-26 12:17:00) [4]

Ок. Приведенное выше проверено и работает. Спасибо всем, что помогли разобраться.


Сергей М.   (2006-07-26 12:02:00) [5]


> Не перепутал?


Да, перепутал.

Конечно же, все наоборот - Count записывается строго при явном указании True.


Сергей М.   (2006-07-26 11:59:00) [6]

Логика вызова ReadStrings(TempList) полностью эквивалентна приведенной тобой логике, нет смысла вызывать сначала ReadInteger(), а затем ReadStrings(TempList, I) - ReadStrings(TempList) делает все тоже самое, но неявно.


DanilinS   (2006-07-26 11:58:00) [7]

Уточнение:
> Если ты умолчал этот параметр или если явно прописал false,
>  то внутри метода WriteStrings в выходной поток сначала
> (1) будет записано Integer-значение, равное кол-ву строк,
>  а следом (2) сами строки,


Не перепутал? при умолчании или false Integer-значение не пишеться

У меня по крайней мере ...


DanilinS   (2006-07-26 11:53:00) [8]

В общем ситуация такова: ReadStrings ждет до бесконечности в готовности принять практически любой обьем данных и обижаеться ошибкой Connection Closed Gracefully на закрытие сервером соединения. Но если WriteStrings (..., true) то сначало посылаеться переменная Integer, которая указывает кол-во записей. Далее на стороне клиента

I:=IdTCPClient1.ReadInteger();
 IdTCPClient1.ReadStrings(TempList, I);


Сергей М.   (2006-07-26 11:53:00) [9]


> Не он-ли заведует передачей данных о кол-ве записей? По
> умолчанию он выключен


Да, именно он и заведует.
Если ты умолчал этот параметр или если явно прописал false, то внутри метода WriteStrings в выходной поток сначала (1) будет записано Integer-значение, равное кол-ву строк, а следом (2) сами строки, в противном случае шаг (1) не выполняется - сразу же выполняется шаг (2).

Тоже самое касается и ReadString - умолчание 2-го параметра или явное его указание (-1) заставляет ожидать/читать из вх.потока сначала Integer-значение, равное кол-ву непосредственно следующих строк.


DanilinS   (2006-07-26 11:39:00) [10]

Похоже нефига не "понимает". Но у WriteStrings есть второй необязательный параметр "const AWriteLinesCount: Boolean = False"

Не он-ли заведует передачей данных о кол-ве записей? По умолчанию он выключен ....


Reindeer Moss Eater   (2006-07-26 11:23:00) [11]

Так и у автора он понимает. Просто сам автор не понимает что такое "Connection Closed Gracefully" .


Сергей М.   (2006-07-26 11:08:00) [12]


> ReadStrings не понимает количество строчек


Долден "понимать", если в ReadStrings и в соответствующем WriteStrings второй параметр умалчивается.


umbra   (2006-07-26 11:06:00) [13]


> Судя по всему ReadStrings не понимает количество строчек

прочтите справку по ReadStrings


DanilinS   (2006-07-26 10:49:00) [14]


> У тебя в кейсе для 03 столько потенциально опасного кода,
>  вызывающего AV, что ручками закрывать и не надо.

Согласен. Потом причешу. Ко кейс рабочий. Завёл Memo и писал логи в него. Кейс отрабатывал штатно без ошибок.

Похоже немного понимаю в чём трабла. Если заменить IdTCPClient1.ReadStrings(TempList) на IdTCPClient1.ReadStrings(TempList,15) то всё работает. Правда читает только первые 15 записей.

Судя по всему ReadStrings не понимает количество строчек. И продолжает читать даже когда сервер отправил данные и закрыл соединение. Похоже придется делать дополнительный запрос ...


Reindeer Moss Eater   (2006-07-25 17:40:00) [15]

Оно (соединение ) почему закрылось? Я его ручками не закрывал ....

У тебя в кейсе для 03 столько потенциально опасного кода, вызывающего AV, что ручками закрывать и не надо.


DanilinS   (2006-07-25 16:48:00) [16]

Оно (соединение ) почему закрылось? Я его ручками не закрывал .... Или отработал блок CommandServerExecute и оно автоматом закрылось, без команды клиента? А как тогда ему подождать, пока клиент данные заберет?

А куда данные делись, которые сервер командой WriteStrings отправил? В клиенте комманда ReadStrings их не получила ... Кроме ошибки ес-но ....


Reindeer Moss Eater   (2006-07-25 16:37:00) [17]

Получаешь, потому что соединение закрылось.


DanilinS   (2006-07-25 16:34:00) [18]

При переносе случайно затер часть строки ... и набил бегом ручками. Что-бы не раздувать тему приходиться часть кода, не относящегося к делу затирать. А что-то забывать затирать. Например строку Int:=IdTCPClient1.ReadInteger(true) в клиенте ... А что почту свою не поставил? Код уже лежал-бы у тебя ....

А что с case не так ? Читаем запись и используем поле с типом byte в case ... 100% рабочий код. Case рабочий.

Непонятно, почему в клиенте при IdTCPClient1.ReadStrings(TempList) получаю ошибку типа "Connection Closed Gracefully" ?


Reindeer Moss Eater   (2006-07-25 16:08:00) [19]

>Сорри ... опечатка. CommandServerExecute естественно

Мы здесь реальный код рассматриваем или опечатки?

Не могу понять, почему не работает следующий код:
Потому что у тебя нет этого кода.


umbra   (2006-07-25 16:00:00) [20]

а как согласуется
case CommandS.Command of
  01: begin  // старт динамического импорта

     ...
      end;


с

TCommand = record
  Command: Byte;
  Name: String [20];
end;


Страницы:   1 2

Наверх

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