-
WinXP, RAD 2009.
Доброй ночи, вечера, дня!
Сейчас принимаю сообщения так:
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
var
s, r: WideString;
begin
try
AContext.Connection.IOHandler.CheckForDisconnect(True, True);
if AContext.Connection.Connected then
begin
s := AContext.Connection.Socket.ReadLn(enUTF8);
............................
AContext.Connection.Socket.WriteLn(_r, GetEncoding);
end;
except
on E: Exception do
begin
if E.ClassType <> EIdConnClosedGracefully then
if E.ClassName <> 'EIdNotConnected' then
if E.ClassName <> 'EIdClosedSocket' then
ShowMessage(E.ClassName + ': ' + E.Message);
end;
end;
end;
Т.е. через ReadLn
А хочется сделать следующее.
Во входящем сообщении будет приходить 2 символа с указанием длины сообщения.
Необходимо сначала прочитать первые два символа сообщения, не удаляя из стека сообщение. Посчитать длину сообщения и считать сообщение с указанной длинной. Удалить сообщение из стека.
Подскажите, пож-та, как можно реализовать такое.
Спасибо.
-
Возможно ли такое через Indy? Или нужно сделать через что-то другое?
-
Для посимвольного чтения буфера предназначен метод Connection.Socket.ReadChar
Важно только понимать что в юникодовой версии символ двухбайтовый.
-
Думаю, что это немножко не то.
Есть функция
AContext.Connection.Socket.ReadString(AButes: Integer; [encoding])
Вот это работает как нужно в плане количества считывания символов.
Но после первого считывания стэк очищается и повторно прочитать сообщение нельзя. Может я чего то неправильно делаю?
-
> стэк очищается и повторно прочитать сообщение нельзя
> Может я чего то неправильно делаю?
Не то что делаешь - думаешь неправильно.
-
Возможно, я не правильно выражаюсь. Не стэк, а входящая очередь.
Я видел где-то, что можно прочитать сообщение без удаления из входящей очереди. А по умолчанию считывается с удалением.
Подскажите, пож-та, как такое делается в Indy. Спасибо.
-
Поясни зачем тебе понадобилось читать сообщение без удаления из очереди ..
-
Считываю некое-количество символов.
Получаю из них длину сообщения.
Считываю сообщение полностью.
-
Ты не ответил на вопрос зачем это делать без удаления из очереди ..
-
Как иначе точно определить размер сообщения?
Ведь если вызвать ReadString с большим числом, чем число символов, то поток будет "висеть" пока не накопится достаточное кол-во символов.
-
> Как иначе точно определить размер сообщения?
Ну ты же сам сказал что размер сообщения у тебя передается в первых двух символах сообщения ?
Вот первые два символа и читай.
> поток будет "висеть"
и что ?
дополнительный пусть себе висит.
а основной можно либо размораживать средствами IdAntifreeze либо предусматривать фиксированный ReadTimeout нужного малого размера
-
Вот прочитал я первые два символа. Определил длину сообщения.
А дальше что делать?
-
А дальше читай сообщение этой длины.
-
Дак собственно, когда пытаюсь прочитать, то получаю кукиш.
L := AContext.Connection.Socket.ReadString(2, enUTF8);
ShowMessage(L);
M := AContext.Connection.Socket.ReadString(StrToInt(L), enUTF8);
ShowMessage(M);
В L загружается 2 первый символа, а M пустая строка.
-
> В L загружается 2 первый символа
И как выглядит их содержимое ?
То что ты видишь соответствует тому что ты передал ?
-
Да, соотвествует.
-
Покажи код передачи ..
-
IdTCPClient1.Connection.Socket.WriteLn(Edit1.Text, enUTF8);
-
И где тут передача префикса 2-х символов с информацией о длине строкового сообщения ?
-
В Edit1.Text сам вписываю. Я ведь пока тестирую. Поэтому сильно код не нагромождаю.
-
> В Edit1.Text сам вписываю
Ужас какой ..
Т.е. если бы не вписал, а просто Edit.Text сразу передавал, то по-твоему строка не передалась бы ?
-
Все бы передалось :)
-
> Все бы передалось
Так а накой же тогда "вписываешь", если "все бы передалось" ?
-
Я имею ввиду, что со стороны клиента все передается. А на стороне сервера, читаются первые 2 символа и все.
-
Ну и читай себе на здоровье на стороне сервера "первые 2 символа и все", в чем проблема-то ?
-
а мне нужно читать первые 2 и все остальные
-
s := AContext.Connection.Socket.ReadLn(enUTF8);
FirstSymbol := s[1]; // вот тебе первый символ
SecondSymbol := s[2]; // вот второй
NextSymbols := Copy(s, 3, Length(s)-2); // а вот тебе все остальные
-
А как сделать такое же, но без ReadLn?
-
А почему собственно WriteLn ?
-
Дак это без разницы. Предполагается, что к данному серверу будут коннектица клиенты написаные не на Delphi. Поэтому не хочется привязываться к чтению строки, а смотреть сколько символов сообщение.
-
> Дак это без разницы
Как это "без разницы" ?
WriteLn передает постфикс - CRLF