Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Работа с сетью в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 22.11.2014, 01:20   #1
Skeich
 
Регистрация: 13.10.2013
Сообщений: 6
Восклицание Передача Record с дин. массивом через SendBuf()

Здравствуйте! Имеется такая структура:

Код:
Type
  TClientData= Record
      ReadBits:Byte;
      CodeMessage:array of byte;
      ArraySize:word;
  End;
Нужно отправить ее с клиента на сервер (и обратно) через сокет, используя SendBuf()
Но, как я ни пытался, ничего годного не выходит. Вот так, например, приходит только часть пакета, и то не те значения, что отправлялись:

Сервер:
Код:
procedure TForm2.ServerSocket1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
  var
  len:integer;
begin

   len:=Socket.ReceiveLength;

 Socket.ReceiveBuf(InputData, len);
// SetLength(InputData.CodeMessage, InputData.ArraySize);

end;
Клиент:

Код:
procedure TForm2.SendClick(Sender: TObject);
var s:string; i,j,k,m:integer;
lel:word;
begin
s:=Edit1.Text;
 ShannonFanoCoding(s);
 Data:=ProcessPacket;


ClientSocket1.Socket.SendBuf(Data, SizeOf(Data));
 Application.ProcessMessages;
end;
Я, конечно, понимаю, что всё это должно выглядеть совсем по-другому, но совершенно не понимаю, как это сделать. Кто-нибудь может на конкретно по шагам пояснить, что и как нужно сделать, чтобы пакеты передавались успешно хотя бы в одну сторону?
Skeich вне форума Ответить с цитированием
Старый 22.11.2014, 10:41   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,792
По умолчанию

Я могу.
Передавай перед массивом его длину. Он у тебя динамический, потому и не передается ничего.
Т.е.
Код:
with ClientSocket1.Socket do begin
 SendBuf(Data.ReadBits, SizeOf(Data.ReadBits));
 SendBuf(Data.ArraySize, SizeOf(Data.ArraySize));
 SendBuf(Data.CodeMessage[0],Data.ArraySize);
end;
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 22.11.2014, 17:45   #3
Skeich
 
Регистрация: 13.10.2013
Сообщений: 6
По умолчанию

А принимать по такому же принципу?

Пытаюсь принимать так, полная чушь приходит:

Код:
procedure TForm2.ServerSocket1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
  var
  len:integer;
  Buf:pointer;
begin

  Socket.ReceiveBuf(InputData.ReadBits, SizeOf(InputData.ReadBits));


  Socket.ReceiveBuf(InputData.ArraySize, SizeOf(InputData.ArraySize));

  SetLength(InputData.CodeMessage, InputData.ArraySize);

  Socket.ReceiveBuf(InputData.CodeMessage, InputData.ArraySize);


end;
Может быть, надо сначала получить Socket.RecieveLength, а потом как-то в цикле принимать только нужное кол-во байт?

Последний раз редактировалось Stilet; 22.11.2014 в 19:01.
Skeich вне форума Ответить с цитированием
Старый 22.11.2014, 19:01   #4
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,792
По умолчанию

Ну да. Сначала байт и слово (или как там порядок) а потом кучу байтов в количистве уже известном.
Цитата:
а потом как-то в цикле принимать только нужное кол-во байт?
Я не знаю как работает этот компонент, но тебе придется организовать цикл, в котором принимать в массив определенное кол-во байт, да еще и в нужное место массива.
Код:
procedure TForm2.ServerSocket1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
  var
  len:integer;
  Buf:pointer;
begin

  Socket.ReceiveBuf(InputData.ReadBits, SizeOf(InputData.ReadBits));
  Socket.ReceiveBuf(InputData.ArraySize, SizeOf(InputData.ArraySize));
  len:=0;
  SetLength(InputData.CodeMessage, InputData.ArraySize);
  repeat
   len:=len+Socket.ReceiveBuf(InputData.CodeMessage[len], InputData.ArraySize);
  until len<Length(InputData.CodeMessage);

end;
I'm learning to live...

Последний раз редактировалось Stilet; 22.11.2014 в 19:04.
Stilet вне форума Ответить с цитированием
Старый 22.11.2014, 21:44   #5
Skeich
 
Регистрация: 13.10.2013
Сообщений: 6
По умолчанию

Ну, в общем-то, всё работает.

Теперь изменил структуру, добавил массив Char и String, и теперь уже они не хотят передаваться. А остальные элементы структуры передаются хорошо.

Структура:
Код:
Type
  TClientData= Record
      ReadBits:Byte;
      CodeMessage:array of byte;
      ArraySize1:word;
      Alphavite:array of char;
      ArraySize2:byte;
      Codes:array of string;
  End;
Отправка:

Код:
procedure TForm2.SendClick(Sender: TObject);
var s:string; i,j,k,m:integer;
lel:word;
begin
s:=Edit1.Text;
 ShannonFanoCoding(s);
 UData:=ProcessPacket;


with ClientSocket1.Socket do begin
 SendBuf(UData.ReadBits, SizeOf(UData.ReadBits));

 SendBuf(UData.ArraySize1, SizeOf(UData.ArraySize1)); //отправляем размер сжатого сообщения
 SendBuf(UData.ArraySize2, SizeOf(UData.ArraySize2)); //отправляем размер алфавита

 SendBuf(UData.CodeMessage[0], UData.ArraySize1);   //  отправляем сжатое сообщение

 SendBuf(UData.Alphavite[0], UData.ArraySize2);  //отправляем алфавит

  SendBuf(UData.Codes[0], UData.ArraySize2); //отправляем коды каждого символа алфавита

end;

end;
Приём:

Код:
procedure TForm2.ServerSocket1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
  var
  len:integer;
  Mes:string;
begin

  Socket.ReceiveBuf(InputData.ReadBits, SizeOf(InputData.ReadBits));     //приняли кол-во значащих битов в последнем байте

  Socket.ReceiveBuf(InputData.ArraySize1, SizeOf(InputData.ArraySize1));  //приняли размер сжатого сообщения в байтах

  Socket.ReceiveBuf(InputData.ArraySize2, SizeOf(InputData.ArraySize2));    //приняли размер алфавита

  len:=0;
  SetLength(InputData.CodeMessage, InputData.ArraySize1);
  repeat
  len:=len+Socket.ReceiveBuf(InputData.CodeMessage[len], InputData.ArraySize1);  //приняли закодированное сообщение
  until len<Length(InputData.CodeMessage);

    len:=0;
  SetLength(InputData.ALphavite, InputData.ArraySize2);
  repeat
  len:=len+Socket.ReceiveBuf(InputData.Alphavite[len], InputData.ArraySize2);
  until len<Length(InputData.Alphavite);

    len:=0;
  SetLength(InputData.Codes, InputData.ArraySize2);
  repeat
  len:=len+Socket.ReceiveBuf(InputData.Codes[len], InputData.ArraySize2);
  until len<Length(InputData.Codes);


   Mes:=Decode(InputData);

end;
Вот так и получается, что Codes и Alphavite не доходят, после выполнения процедуры приёма буфера там находятся пустые символы и #0 соответственно. Ну и, естественно, вопрос, куда дальше воевать? МОжет быть их(Codes и Alphavite) можно передать как-то более удобно?

UPD.: Поменял все знаки '<' на '<=', теперь доходят первые два символа алфавита, а дальше тоже самое..

Последний раз редактировалось Skeich; 22.11.2014 в 22:04.
Skeich вне форума Ответить с цитированием
Старый 23.11.2014, 00:11   #6
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,792
По умолчанию

Цитата:
len:=len+Socket.ReceiveBuf(InputDat a.Codes[len], InputData.ArraySize2);
И ты решил что со строками прокатит такая фишка???
Красавчик )
Может тогда тебе сначала стоит поглубже изучить компонент ServerSocket и его принцип работы? А потом ответь себе на вопрос - почему используешь именно его.
Ведь есть другие компоненты, у которых функционал поболее и поудобнее. Я намекаю на INDI.
Просто если продолжишь писать так и далее тебе придется учитывать много факторов. Например склейка пакетов. И если с отправкой одномерного массива все просто - считаешь в цикле сколько пришло и сколько осталось, то массив строк - двумерный массив байт, а тут уже придется изголиться, и делить пришедший пакет не только на элементы массива, а еше и на элементы строки.
В общем так! Вот что бы я сделал на твоем месте: Засунул всю информацию в Stream. Естесственно структурировав ее как-то, а потом по FTP передал бы ее серверу.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 23.11.2014, 10:56   #7
Skeich
 
Регистрация: 13.10.2013
Сообщений: 6
По умолчанию

Цитата:
Сообщение от Stilet Посмотреть сообщение
И ты решил что со строками прокатит такая фишка???
Красавчик )
Может тогда тебе сначала стоит поглубже изучить компонент ServerSocket и его принцип работы? А потом ответь себе на вопрос - почему используешь именно его.
Ведь есть другие компоненты, у которых функционал поболее и поудобнее. Я намекаю на INDI.
Просто если продолжишь писать так и далее тебе придется учитывать много факторов. Например склейка пакетов. И если с отправкой одномерного массива все просто - считаешь в цикле сколько пришло и сколько осталось, то массив строк - двумерный массив байт, а тут уже придется изголиться, и делить пришедший пакет не только на элементы массива, а еше и на элементы строки.
В общем так! Вот что бы я сделал на твоем месте: Засунул всю информацию в Stream. Естесственно структурировав ее как-то, а потом по FTP передал бы ее серверу.
А чем этот самый Indy удобнее именно для моего случая? Еще возникла идея сохранять два этих массива в файл и передавать его через этот же Indy, а пакет со сжатым сообщением по-прежнему через Sendbuf
Skeich вне форума Ответить с цитированием
Старый 23.11.2014, 11:37   #8
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,792
По умолчанию

Цитата:
А чем этот самый Indy удобнее именно для моего случая?
А хотя бы тем что не придется думать о склейке пакетов. То что передано придет одним блоком. Можно обойтись без цикла считывания.
Повторю идею: Данные засовываешь в TMemoryStream, передаешь по FTP. Принимающая сторона получает их в виде TStream (Потому я на FTP и намекаю), который ты уже разбираешь по прибытии.
Упрощается сама паковка и передача данных.
Цитата:
Еще возникла идея
Плохая идея. Это я тебе говорю из своего опыта создания WEB серверов и FTP серверов. Я на передаче данных уже собаку съел, так что поверь - тот компонент что ты сейчас выбрал тебе на данном этапе не подходит.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 23.11.2014, 19:22   #9
Skeich
 
Регистрация: 13.10.2013
Сообщений: 6
По умолчанию

Цитата:
Сообщение от Stilet Посмотреть сообщение
А хотя бы тем что не придется думать о склейке пакетов. То что передано придет одним блоком. Можно обойтись без цикла считывания.
Это Вы о FTP или Indy?
Skeich вне форума Ответить с цитированием
Старый 23.11.2014, 19:39   #10
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,792
По умолчанию

Это я о компонентах IdFTP(Server) от INDI.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Файлы и дин. переменные. Изменить с использованием дин. переменных. Маленыч Паскаль, Turbo Pascal, PascalABC.NET 4 07.06.2012 11:17
передать массив через Socket.SendBuf(); raketa161 Работа с сетью в Delphi 14 19.05.2012 15:01
из дин. дека в дин. стек (Borland С++) mego4el Помощь студентам 1 07.07.2011 14:41
Передача записи (Record) с данными посети (Indy) Archangel_x Работа с сетью в Delphi 3 06.06.2011 11:38
передача данных типа Record... Рустам Работа с сетью в Delphi 4 24.01.2010 09:51