![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
O пересылке данных с TIdTCPServer [D7, WinXP]
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;