![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
String To array of byte [D7, XP]
ex32Le © (2006-08-15 20:54:00)Имеем такую структуру:
TRecvPacket = record
RData: array[0..1024] of byte;
RLen: Word;
end;
В дальнейшем, принимаю данные из сокета как String:
procedure SZ2SocketOnData(Sender: TObject);
var
tmp: TRecvPacket;
tmprecv:string;
begin
tmprecv := SZ2Socket.ReceiveStr;
tmp.RLen := Length(tmprecv);
Move(tmprecv[1],tmp.RData[0],length(tmprecv));
HdlRecvData(tmp, length(tmprecv));
end;
HdlRecvData -- приблизительно такого вида:
procedure HdlRecvData(buffer: Pointer; bufferLen: LongWord);
....
В нем идет разбор пришедшего пакета.
В чем проблема? В HdlRecvData у меня проверяется валидность пакета, его разбор и т.д.
Но есть небольшая проблема, иногда при обработке пакетов, не проходит валидность, т.е. пакет не правильным образом доставляется от сокета до моей процедуры. Я бы копал конечно в сторону, как раз начинки HdlRecvData, НО, попробовал сделать вместо
Move(tmprecv[1],tmp.RData[0],length(tmprecv));
На:
for i := 0 to length(tmprecv) do
tmp.RData[i] := ord(tmprecv[i+1]);
И всё работает без сбоев. Но мне не нравится такое рашение. Что посоветуете?
Германн (2006-08-16 00:32:00) [1]
> Наверное стоит немного оговорить ситуацию, дело в том что
> первые штук 10 пактов с сервера обрабатывались нормально,
> а потом приходит сразу 3-4 подряд с сервера, вот в этот
> - то момент всё и происходило, я понять не мог.
Может стоило подумать о том, что пакет принятый из сокета не обязан содержать целоечисло структур TRecvPacket? И организовать приёмный буфер, куда сваливать принятое, анализировать на "валидность" часть буфера, валидные куски после анализа копировать куда надо, удаляя при этом из буфера, а недопринятую информацию оставлять до будущих времён?
ex32Le (2006-08-15 22:56:00) [2]Наверное стоит немного оговорить ситуацию, дело в том что первые штук 10 пактов с сервера обрабатывались нормально, а потом приходит сразу 3-4 подряд с сервера, вот в этот - то момент всё и происходило, я понять не мог.
Вобщем сравнил я содержимое массивов, даже не знаю к какому выводу я пришел, но решил на всякий случай проверять длину пакета перед Move
if length(tmprecv) <= 0 then exit;
И как не странно, вроде всё стабилизировалось.
ex32Le (2006-08-15 22:56:00) [3]Наверное стоит немного оговорить ситуацию, дело в том что первые штук 10 пактов с сервера обрабатывались нормально, а потом приходит сразу 3-4 подряд с сервера, вот в этот - то момент всё и происходило, я понять не мог.
Вобщем сравнил я содержимое массивов, даже не знаю к какому выводу я пришел, но решил на всякий случай проверять длину пакета перед Move
if length(tmprecv) <= 0 then exit;
И как не странно, вроде всё стабилизировалось.
ex32Le (2006-08-15 22:20:00) [4]
> Вы действительно добавили строку из [1] сразу после вызова
> Move?
Да, сейчас для надежности снова проверил, но не помогло.
Сейчас работает корректно только при:
> Move(tmprecv[1],t1.Data[0],length(tmprecv)+1);
Чуть позднее попробую сравнить массивы.
begin...end (2006-08-15 22:09:00) [5]> ex32Le (15.08.06 22:01) [6]
Тогда [1], насколько я понимаю, должно работать. Вы действительно добавили строку из [1] сразу после вызова Move? Если всё-таки не работает, сравните (с помощью отладчика) содержимое массива tmp.RData (первые RLen+1 байт) непосредственно перед вызовом HdlRecvData в случаях [1] и [3].
ex32Le (2006-08-15 22:01:00) [6]
ShowMessage(IntToStr(tmp.RData[tmp.RLen]))
Возвращает (выводит) 0.
begin...end (2006-08-15 21:40:00) [7]ОК. Теперь после вызова Move (с учётом [3]) добавьте строчку
ShowMessage(IntToStr(tmp.RData[tmp.RLen]))и выполните код несколько раз. Какое число показывает сообщение?
ex32Le (2006-08-15 21:30:00) [8]
> length(tmprecv) + 1
Да, попробовал -- работает.
begin...end (2006-08-15 21:24:00) [9]Изменяется ли что-нибудь, если в Move вместо length(tmprecv) передавать length(tmprecv) + 1? В случае успеха это нельзя будет оставить в качестве конечного варианта, но всё же проверьте.
ex32Le (2006-08-15 21:16:00) [10]
> После вызова Move добавьте строку tmp.RData[tmp.RLen] :=
> 0.
Увы, не помогло.
begin...end (2006-08-15 21:06:00) [11]После вызова Move добавьте строку
tmp.RData[tmp.RLen] := 0. Сообщите результат.
Второй вариант приведённого кода, строго говоря, некорректен.