Страница 1 из 1
Как правильно передать/прочитать запись по TUDPBlockSocket?
Добавлено:
11.03.2016 12:31:54
kosteek
Сделал такой вид записи с динамическим массивом
- Код: Выделить всё
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. Структуру считывает до динамического массива правильно, но в динамический массив попадает ерунда.
Но если вместо динамического массива использовать обычный массив, все замечательно работает.
Re: Как правильно передать/прочитать запись по TUDPBlockSock
Добавлено:
11.03.2016 12:48:47
Дож
Динамический массив не хранится сам в записи, в записи хранится только указатель на то место в памяти, где реально размещён динамический массив. sizeof(ons) — это не функция, а константа. Сериализовать динамический массив нужно самостоятельно. Например, записав сперва длину массива, потом все его элементы.
Re: Как правильно передать/прочитать запись по TUDPBlockSock
Добавлено:
11.03.2016 15:03:38
kosteek
Спасибо Дож. Тоже самое будет если вместо динамического массива укажу тип String.
Массив сериализовал
- Код: Выделить всё
SetLength(msg.msg, length(s));
for i:=0 to length(s)-1 do msg.msg[i]:=s[i+1];
Подскажи как правильно отправить?
Re: Как правильно передать/прочитать запись по TUDPBlockSock
Добавлено:
11.03.2016 15:11:26
Дож
Что будет со String зависит от того, является ли он алиасом на AnsiString (в этом случае действительно как дин. массив ведёт себя) или ShortSring (в этом случае хранит строку по месту).
Re: Как правильно передать/прочитать запись по TUDPBlockSock
Добавлено:
11.03.2016 16:12:09
wavebvg
kosteek, string будет указывать на адрес первого байта PChar-а.
Данные не имеющие фиксированного (максимального) размера не получится прочитать за одну операцию (вначале читаем размер, потом данные).
Если есть какие-либо ограничения сверху на размер ons - то лучше использовать массив фиксированной длины.
Если ограничения нет - тогда можно в отправляемый буфер с ons в конец дописать данные из msg. При чтении, вначале, читаем ons, а потом, зная размер, читаем оставшиеся данные в заранее подготовленный буфер и назначаем его [буфер] msg-у.
Re: Как правильно передать/прочитать запись по TUDPBlockSock
Добавлено:
11.03.2016 16:26:10
kosteek
wavebvg, а как отправить в одном udp пакете ons и msg?
Re: Как правильно передать/прочитать запись по TUDPBlockSock
Добавлено:
11.03.2016 17:02:48
Дож
kosteek писал(а):wavebvg, а как отправить в одном udp пакете ons и msg?
Нужно в этом сообщении сперва записать ons (без массива), потом длину массива, потом элементы массива.
Re: Как правильно передать/прочитать запись по TUDPBlockSock
Добавлено:
12.03.2016 12:37:48
wavebvg
Посмотрел, как сейчас в синапсе.
Проще всего так (идея - засунуть даные в строку и не маяться с её управлением, сам не проверял):
- Код: Выделить всё
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);
Re: Как правильно передать/прочитать запись по TUDPBlockSock
Добавлено:
12.03.2016 15:21:19
kosteek
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;
Еще раз поблагодарю всех кто участвовал в обсуждении.