Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Сети > Динамический массив в Record и отправка его через


Автор: lux16 18.4.2011, 13:08
Привет, народ. Столкнулся с проблемой. Есть такая структура:
Код

 aData = Packed Record
    aArr:   Array Of String;
  End;

И такие процедуры:
Код

procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
  Socket: TCustomWinSocket);
var
  rec:  aData;
begin
  SetLength( rec.aArr, 3 );
  rec.aArr[1] := '1';
  rec.aArr[2] := '2';
  Socket.SendBuf( rec, SizeOf( rec ) );
end;

procedure TForm1.ClientSocket1Read(Sender: TObject;
  Socket: TCustomWinSocket);
var
  rec:  aData;
  len:  Byte;
begin
  len := Socket.ReceiveLength;
  Socket.ReceiveBuf( rec, len );
  Memo1.Lines.Add( rec.aArr[1] );
end;

И в Memo1 просто добовляется пустая строка, но если в процедуре procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket); добавить строку ShowMessage( '' );, то есть привести ее к такому виду:
Код

procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
  Socket: TCustomWinSocket);
var
  rec:  aData;
begin
  SetLength( rec.aArr, 3 );
  rec.aArr[1] := '1';
  rec.aArr[2] := '2';
  Socket.SendBuf( rec, SizeOf( rec ) );
  ShowMessage( '' );
end;

То все работает, и в Memo1 добовляется строка. Подскажите, что кто знает

Автор: Snowy 18.4.2011, 14:15
А какой смысл передавать по сети массив указателей на строку?
Даже в пределах одной программы это странная затея...
А во втором случае работает потому, что ты стопоришь выход из функции.
Если остановки не будет, то твои строки перестают существовать.
А так, как ты переслал не строки, а указатели на них, то эти указатели будут показывать на ничто, т.к. строк в памяти уже нет.

Автор: lux16 18.4.2011, 14:25
Либо я что - то не понял, либо что - то не так. Мне нужно передавать строки переменной величины, то есть я их размер не знаю. Для этого мне надо Array Of String. Как его передать расскажите, никакой указатель я не передаю

Добавлено через 10 минут и 5 секунд
Всем спасибо, нашел решение. На форуме programmersforum помогли. После отправки пишу такой код Application.ProccesMessages;

Автор: Snowy 18.4.2011, 15:03
Что такое string?
Это указатель на блок данных в памяти, где находится текст и длина строки.
Таким образом, array of string - массив указателей.
Вот его ты и передаёшь.
Повторяю - ты передаёшь не строки.
Как только ты выйдешь за пределы своей программы (например пересылка между двумя компьютерами или двумя программами), твои указатели потеряют весь смысл.

Это, что касается того, что ты делаешь неправильно.
Теперь о том, как нужно делать.
Вместо array of string используй TStringList.
А дальше обычное правило пересылки данных нефиксированной длины.
Сначала отправляешь 4 байта - размер данных, потом сами данные.
В твоём случае это 
Socket.SendBuf(Length(StringList.Text), 4);
Socket.SendBuf(StringList.Text[1], Length(StringList.Text) * SizeOf(char));

Автор: kami 18.4.2011, 18:51
Цитата(lux16 @  18.4.2011,  14:25 Найти цитируемый пост)
После отправки пишу такой код Application.ProccesMessages;

Это костыль. Причем плохой костыль.

Автор: lux16 19.4.2011, 09:45
Млин, помогите разобраться

Автор: Snowy 19.4.2011, 10:08
Сформируй весь текст через TStringList, потом возьми весь текст одной строкой - TStringList.Text.
Передай длину текста.
Передай сам текст.
Я уже дал 2 строки отправки.
Как принять:
Код

Socket.ReceiveBuf(len, 4);
SetLength(s, len);
Socket.ReceiveBuf(s[1], len * SizeOf(char));
StringList.Text := s;
где 
len: integer - длина текста в символах
s: string - строка, в которую принять текст.
StringList - результат, в который положить принятый текст.
Вместо StringList можешь использовать любой TStrings (например Memo1.Lines)
Как работать с TStrings/TStringList, надеюсь знаешь.
Ну и, как дополнительный совет - всю работу с сокетами помещай в try блок.
Ибо исключения при работе с сетью - обычное дело.

Добавлено через 8 минут и 38 секунд
Проще нарисовать...
Код

procedure TForm1.ServerSocket1ClientConnect(Sender: TObject; Socket: TCustomWinSocket);
var
  sl: TStringList;
  len: integer;
begin
  sl := TStringList.Create();
  sl.Add('Строка №раз');
  sl.Add('А это вторая строка');
  sl.Add('Эта строка последняя!');
  sl.Add('Честное слово');
  sl.Add('А вот и нет! Я вас обманул!');
  try
    len := sl.Text.Length;
    Socket.SendBuf(len, SizeOf(len));
    Socket.SendBuf(sl.Text[1], len * SizeOf(char));
  finally
    sl.Free;
  end;
end;

procedure TForm1.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
var
  len:  Integer;
  s:    string;
begin
  try
    Socket.ReceiveBuf(len, SizeOf(len));
    SetLength(s, len);
    Socket.ReceiveBuf(s[1], len * SizeOf(char));
    Memo1.Lines.Text := s;
  finally
  end;
end;
Писал прямо в браузере - не проверял. Но ошибок вроде нет.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)