Как правильно передать/прочитать запись по TUDPBlockSocket?

Общие вопросы программирования, алгоритмы и т.п.

Модератор: Модераторы

Как правильно передать/прочитать запись по TUDPBlockSocket?

Сообщение kosteek » 11.03.2016 12:31:54

Сделал такой вид записи с динамическим массивом
Код: Выделить всё
type
  ons = record
    version: Byte;
    statusPacket: Byte;
    statusClient: Byte;
    lengthIdentify: Byte;
    Identefer: array[0..31] of char;
    lengthMsg: integer;
    msg:array of char;
  end;

Код: Выделить всё
UDPServer: TUDPBlockSocket;
msg: ons;

Код: Выделить всё
UDPServer.RecvBuffer(@msg,sizeof(ons));


Не могу понять как правильно прочитать его с помощью TUDPBlockSocket. Структуру считывает до динамического массива правильно, но в динамический массив попадает ерунда.

Но если вместо динамического массива использовать обычный массив, все замечательно работает.
kosteek
постоялец
 
Сообщения: 203
Зарегистрирован: 24.07.2008 14:57:09
Откуда: Украина, г.Славянск

Re: Как правильно передать/прочитать запись по TUDPBlockSock

Сообщение Дож » 11.03.2016 12:48:47

Динамический массив не хранится сам в записи, в записи хранится только указатель на то место в памяти, где реально размещён динамический массив. sizeof(ons) — это не функция, а константа. Сериализовать динамический массив нужно самостоятельно. Например, записав сперва длину массива, потом все его элементы.
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Как правильно передать/прочитать запись по TUDPBlockSock

Сообщение kosteek » 11.03.2016 15:03:38

Спасибо Дож. Тоже самое будет если вместо динамического массива укажу тип String.
Массив сериализовал
Код: Выделить всё
  SetLength(msg.msg, length(s));
  for i:=0 to length(s)-1 do msg.msg[i]:=s[i+1];

Подскажи как правильно отправить?
Последний раз редактировалось kosteek 11.03.2016 15:13:36, всего редактировалось 1 раз.
kosteek
постоялец
 
Сообщения: 203
Зарегистрирован: 24.07.2008 14:57:09
Откуда: Украина, г.Славянск

Re: Как правильно передать/прочитать запись по TUDPBlockSock

Сообщение Дож » 11.03.2016 15:11:26

Что будет со String зависит от того, является ли он алиасом на AnsiString (в этом случае действительно как дин. массив ведёт себя) или ShortSring (в этом случае хранит строку по месту).
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Как правильно передать/прочитать запись по TUDPBlockSock

Сообщение wavebvg » 11.03.2016 16:12:09

kosteek, string будет указывать на адрес первого байта PChar-а.
Данные не имеющие фиксированного (максимального) размера не получится прочитать за одну операцию (вначале читаем размер, потом данные).
Если есть какие-либо ограничения сверху на размер ons - то лучше использовать массив фиксированной длины.
Если ограничения нет - тогда можно в отправляемый буфер с ons в конец дописать данные из msg. При чтении, вначале, читаем ons, а потом, зная размер, читаем оставшиеся данные в заранее подготовленный буфер и назначаем его [буфер] msg-у.
wavebvg
постоялец
 
Сообщения: 354
Зарегистрирован: 28.02.2008 04:57:35

Re: Как правильно передать/прочитать запись по TUDPBlockSock

Сообщение kosteek » 11.03.2016 16:26:10

wavebvg, а как отправить в одном udp пакете ons и msg?
kosteek
постоялец
 
Сообщения: 203
Зарегистрирован: 24.07.2008 14:57:09
Откуда: Украина, г.Славянск

Re: Как правильно передать/прочитать запись по TUDPBlockSock

Сообщение Дож » 11.03.2016 17:02:48

kosteek писал(а):wavebvg, а как отправить в одном udp пакете ons и msg?

Нужно в этом сообщении сперва записать ons (без массива), потом длину массива, потом элементы массива.
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Как правильно передать/прочитать запись по TUDPBlockSock

Сообщение wavebvg » 12.03.2016 12:37:48

Посмотрел, как сейчас в синапсе.

Проще всего так (идея - засунуть даные в строку и не маяться с её управлением, сам не проверял):
Код: Выделить всё
var
  Msg, Resp: ons;
  Send, Recv: TStringStream;

Записываем данные:
Код: Выделить всё
Send.Write(Msg, SizeOf(Msg) - SizeOf(Msg.msg));
Send.Write(Msg.msg[1], Length(Msg.msg));

Отправляем данные:
Код: Выделить всё
UDPServer.SendString(Send.DataString);

Читаем данные ответа:
Код: Выделить всё
Recv.DataString := Socket.RecvString(5000);

Заполняем структуру:
Код: Выделить всё
Recv.Position := 0;
Recv.Read(Resp, SizeOf(Resp) - SizeOf(Resp.msg));
SetLength(Resp.msg, Resp.lengthMsg);
Recv.Read(Resp.msg[1], Resp.lengthMsg);
wavebvg
постоялец
 
Сообщения: 354
Зарегистрирован: 28.02.2008 04:57:35

Re: Как правильно передать/прочитать запись по TUDPBlockSock

Сообщение kosteek » 12.03.2016 15:21:19

wavebvg, благодарю, получилось отправлять и получать.
изменил запись, вместо динамического массива использую String
Код: Выделить всё
type
  ons = record
    version: Byte;
    statusPacket: Byte;
    statusClient: Byte;
    lengthIdentify: Byte;
    Identefer: array[0..31] of char;
    lengthMsg: integer;
    msg:string;
  end;

Твой пример с запись отлично сработал, а вот с чтением повозился.
Рабочий код чтения
Код: Выделить всё
procedure TUDPServer.Execute;
var
  msg : ons;
  Recv:TStringStream;
  s:string;
begin

  while (not Terminated) do
    begin
        s:='';
        msg.msg:='';
        Recv:=TStringStream.Create(s);
        recv.WriteString(UDPServer.RecvPacket (100));
        Recv.Position:=0;
        if Recv.Size > 0 then
          begin
               Recv.Read(msg,sizeof(msg)-sizeof(msg.msg));
               if msg.lengthMsg > 0 then
                 begin
                      msg.lengthMsg:=LEtoN(msg.lengthMsg);
                      SetLength(msg.msg,msg.lengthMsg);
                      msg.msg:=Recv.ReadString(msg.lengthMsg);

                 end;
               fStatusText := msg;
               Synchronize(@Showstatus);

          end;
        FreeAndNil(Recv);
    end;
end;


Еще раз поблагодарю всех кто участвовал в обсуждении.
kosteek
постоялец
 
Сообщения: 203
Зарегистрирован: 24.07.2008 14:57:09
Откуда: Украина, г.Славянск


Вернуться в Общее

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 20

Рейтинг@Mail.ru