Форум: "Сети";
Текущий архив: 2007.01.07;
Скачать: [xml.tar.bz2];
ВнизO пересылке данных с TIdTCPServer Найти похожие ветки
← →
DanilinS (2006-07-25 15:15) [0]Необходимо дергать данные с сервера. Данные структурированы но их обьем заренее не известен.
Не могу понять, почему не работает следующий код:
Сервер:
код:
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 через сетку протащить?
← →
Reindeer Moss Eater © (2006-07-25 15:27) [1]При чем здесь обработчик CommandServerException?
Что такое CommandS?
← →
DanilinS (2006-07-25 15:51) [2]Сорри ... опечатка. CommandServerExecute естественно
CommandS: TCommand;
TCommand = record
Command: Byte;
Name: String [20];
end;
← →
umbra © (2006-07-25 15:51) [3]
> CommandServerException
А почему обработку команд Вы вешаете на обработчик исключений, возникающих в потоке, работающем с клиентом?
← →
umbra © (2006-07-25 16:00) [4]а как согласуется
case CommandS.Command of
01: begin // старт динамического импорта
...
end;
сTCommand = record
Command: Byte;
Name: String [20];
end;
← →
Reindeer Moss Eater © (2006-07-25 16:08) [5]>Сорри ... опечатка. CommandServerExecute естественно
Мы здесь реальный код рассматриваем или опечатки?
Не могу понять, почему не работает следующий код:
Потому что у тебя нет этого кода.
← →
DanilinS (2006-07-25 16:34) [6]При переносе случайно затер часть строки ... и набил бегом ручками. Что-бы не раздувать тему приходиться часть кода, не относящегося к делу затирать. А что-то забывать затирать. Например строку Int:=IdTCPClient1.ReadInteger(true) в клиенте ... А что почту свою не поставил? Код уже лежал-бы у тебя ....
А что с case не так ? Читаем запись и используем поле с типом byte в case ... 100% рабочий код. Case рабочий.
Непонятно, почему в клиенте при IdTCPClient1.ReadStrings(TempList) получаю ошибку типа "Connection Closed Gracefully" ?
← →
Reindeer Moss Eater © (2006-07-25 16:37) [7]Получаешь, потому что соединение закрылось.
← →
DanilinS (2006-07-25 16:48) [8]Оно (соединение ) почему закрылось? Я его ручками не закрывал .... Или отработал блок CommandServerExecute и оно автоматом закрылось, без команды клиента? А как тогда ему подождать, пока клиент данные заберет?
А куда данные делись, которые сервер командой WriteStrings отправил? В клиенте комманда ReadStrings их не получила ... Кроме ошибки ес-но ....
← →
Reindeer Moss Eater © (2006-07-25 17:40) [9]Оно (соединение ) почему закрылось? Я его ручками не закрывал ....
У тебя в кейсе для 03 столько потенциально опасного кода, вызывающего AV, что ручками закрывать и не надо.
← →
DanilinS (2006-07-26 10:49) [10]
> У тебя в кейсе для 03 столько потенциально опасного кода,
> вызывающего AV, что ручками закрывать и не надо.
Согласен. Потом причешу. Ко кейс рабочий. Завёл Memo и писал логи в него. Кейс отрабатывал штатно без ошибок.
Похоже немного понимаю в чём трабла. Если заменить IdTCPClient1.ReadStrings(TempList) на IdTCPClient1.ReadStrings(TempList,15) то всё работает. Правда читает только первые 15 записей.
Судя по всему ReadStrings не понимает количество строчек. И продолжает читать даже когда сервер отправил данные и закрыл соединение. Похоже придется делать дополнительный запрос ...
← →
umbra © (2006-07-26 11:06) [11]
> Судя по всему ReadStrings не понимает количество строчек
прочтите справку поReadStrings
← →
Сергей М. © (2006-07-26 11:08) [12]
> ReadStrings не понимает количество строчек
Долден "понимать", если в ReadStrings и в соответствующем WriteStrings второй параметр умалчивается.
← →
Reindeer Moss Eater © (2006-07-26 11:23) [13]Так и у автора он понимает. Просто сам автор не понимает что такое "Connection Closed Gracefully" .
← →
DanilinS (2006-07-26 11:39) [14]Похоже нефига не "понимает". Но у WriteStrings есть второй необязательный параметр "const AWriteLinesCount: Boolean = False"
Не он-ли заведует передачей данных о кол-ве записей? По умолчанию он выключен ....
← →
Сергей М. © (2006-07-26 11:53) [15]
> Не он-ли заведует передачей данных о кол-ве записей? По
> умолчанию он выключен
Да, именно он и заведует.
Если ты умолчал этот параметр или если явно прописал false, то внутри метода WriteStrings в выходной поток сначала (1) будет записано Integer-значение, равное кол-ву строк, а следом (2) сами строки, в противном случае шаг (1) не выполняется - сразу же выполняется шаг (2).
Тоже самое касается и ReadString - умолчание 2-го параметра или явное его указание (-1) заставляет ожидать/читать из вх.потока сначала Integer-значение, равное кол-ву непосредственно следующих строк.
← →
DanilinS (2006-07-26 11:53) [16]В общем ситуация такова: ReadStrings ждет до бесконечности в готовности принять практически любой обьем данных и обижаеться ошибкой Connection Closed Gracefully на закрытие сервером соединения. Но если WriteStrings (..., true) то сначало посылаеться переменная Integer, которая указывает кол-во записей. Далее на стороне клиента
I:=IdTCPClient1.ReadInteger();
IdTCPClient1.ReadStrings(TempList, I);
← →
DanilinS (2006-07-26 11:58) [17]Уточнение:
> Если ты умолчал этот параметр или если явно прописал false,
> то внутри метода WriteStrings в выходной поток сначала
> (1) будет записано Integer-значение, равное кол-ву строк,
> а следом (2) сами строки,
Не перепутал? при умолчании или false Integer-значение не пишеться
У меня по крайней мере ...
← →
Сергей М. © (2006-07-26 11:59) [18]Логика вызова ReadStrings(TempList) полностью эквивалентна приведенной тобой логике, нет смысла вызывать сначала ReadInteger(), а затем ReadStrings(TempList, I) - ReadStrings(TempList) делает все тоже самое, но неявно.
← →
Сергей М. © (2006-07-26 12:02) [19]
> Не перепутал?
Да, перепутал.
Конечно же, все наоборот - Count записывается строго при явном указании True.
← →
DanilinS (2006-07-26 12:17) [20]Ок. Приведенное выше проверено и работает. Спасибо всем, что помогли разобраться.
← →
Сергей М. © (2006-07-26 12:23) [21]В условиях глоб.сети твой код может споткнуться еще об одни грабли.
Посмотри внимательно на ф-цию Get/SetSockOpt и опции SO_LINGER/SO_DONTLINGER.
← →
DanilinS (2006-08-11 15:35) [22]В догонку вопрос:
Если на стороне сервера (TIdTCPServer) используеться функция AThread.Connection.WriteFile
то какой функцией TIdTCPClient эти данные можно принять "оптом" (не по байтно)?
функцией IdTCPClient1.ReadStream ? Какой Stream нужно в этом случае использовать? (TMemoryStream ?)
← →
Сергей М. © (2006-08-11 15:41) [23]
> Какой Stream нужно в этом случае использовать? (TMemoryStream
> ?)
Любой наследник TStream
Страницы: 1 вся ветка
Форум: "Сети";
Текущий архив: 2007.01.07;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.02 c