Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Интернет и сети
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 07.06.2013, 08:58
Ioanwar Ioanwar вне форума
Прохожий
 
Регистрация: 07.06.2013
Сообщения: 9
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию Сокеты, динамические массивы, боль, страдания...

В общем такая проблема...
Есть Сервер и Клиент, которые перебрасываются между собой динамическими массивами. Отправка и принятие у сервера работает отлично, но вот клиент не может нормально принять массив...
Точнее он его принимает, но либо программа сама закрывается, либо при закрытии Клиента выдает ошибку "invalid pointer operation".
Для начала я проверил, что может быть я не правильно работаю с массивом, но нет, обращение к данным в этом массиве происходит без ошибок...
Ниже привожу код программы:

Код Клиента при принятии:
Код:
procedure TForm1.CSRead(Sender: TObject; Socket: TCustomWinSocket);
 begin
 try
 ct:=0;
 ct:=(CS.Socket.ReceiveLength div 4)div 768;
 SetLength(Adm,ct);
 CS.Socket.ReceiveBuf(Adm[0],CS.Socket.ReceiveLength);
 List.Clear;
 for i:=0 to High(Adm) do
 List.Items.Add(Adm[i].Name+' '+'('+Adm[i].ip+')'+Adm[i].roll);
 finally
 SetLength(Adm,0);
 end;
 end;
Код отправки от сервера:
Код:
SetLength(Mass,j);
 for f:=0 to High(Mass) do 
 Begin
 Mass[f].Name:=NameHost[f];
 Mass[f].ip:=IP[f];
 Mass[f].roll:=Roll[f];
 end;
 SS.Socket.Connections[i].SendBuf(Mass[0],SizeOf(Mass)*Length(Mass)*768); // i-задается в другом месте
 SetLength(Mass,0);
Админ: Учимся корректно оформлять код!

в общем когда приходит массив размерностью 1, то выдает "invalid pointer operation" послы выхода из программы.
а когда приходит массив более 1 строк, то программа вылетает с ошибкой "access violation ...".

Помомгите люди добрые

Последний раз редактировалось Admin, 07.06.2013 в 09:32.
Ответить с цитированием
  #2  
Старый 07.06.2013, 09:01
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

а почему буферу устанавливается размер в 3072 раза меньше, чем запрашивается данных?
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
  #3  
Старый 07.06.2013, 09:17
Ioanwar Ioanwar вне форума
Прохожий
 
Регистрация: 07.06.2013
Сообщения: 9
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Цитата:
Сообщение от NumLock
а почему буферу устанавливается размер в 3072 раза меньше, чем запрашивается данных?
Не понял, вроде все нормально... или я болею. Много не спал, если можете тыкните своим свежим взглядом мне в нос кодом, где у меня косяк)))

Цитата:
SS.Socket.Connections[i].SendBuf(Mass[0],SizeOf(Mass)*Length(Mass)*768)

SizeOf(Mass) = 4
Умножаем на количество элементов в массиве, за тем умножаем на размер 3-х строк (768) в каждом элементе этого массива

Цитата:
CS.Socket.ReceiveBuf(Adm[0],CS.Socket.ReceiveLength);
Принимаем и записываем в Adm, при этом в CS.Socket.ReceiveLength приходит результат этого:SizeOf(Mass)*Length(Mass)*768

Последний раз редактировалось Ioanwar, 07.06.2013 в 09:28.
Ответить с цитированием
  #4  
Старый 07.06.2013, 09:25
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

Код:
1. ct:=(CS.Socket.ReceiveLength div 4)div 768;
2. SetLength(Adm,ct);
3. CS.Socket.ReceiveBuf(Adm[0],CS.Socket.ReceiveLength);
1. переменная ct принимает значение равное ReceiveLength / 3072
2. массиву Adm назначается этот размер
3. из сокета запрашиваются данные в массив Adm с максимальным размером равным ReceiveLength, т.е. в 3072 раза больше, чем сам массив
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
  #5  
Старый 07.06.2013, 09:35
Ioanwar Ioanwar вне форума
Прохожий
 
Регистрация: 07.06.2013
Сообщения: 9
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Цитата:
Сообщение от NumLock
Код:
1. ct:=(CS.Socket.ReceiveLength div 4)div 768;
2. SetLength(Adm,ct);
3. CS.Socket.ReceiveBuf(Adm[0],CS.Socket.ReceiveLength);
1. переменная ct принимает значение равное ReceiveLength / 3072
2. массиву Adm назначается этот размер
3. из сокета запрашиваются данные в массив Adm с максимальным размером равным ReceiveLength, т.е. в 3072 раза больше, чем сам массив
В первой строке я узнаю количество элементов в массиве, во второй строке я создаю массив с этим количесвом элементов, и в 3й строке я принимаю в этот массив данные... т.е. ReceiveBuf(Adm[0],CS.Socket.ReceiveLength);
где Adm[0]- адрес, а CS.Socket.ReceiveLength задаю размер буфера.
т.е. по идее второй параметр ReceiveBuf я указываю размер буффера а не размер массива
Ответить с цитированием
  #6  
Старый 07.06.2013, 09:39
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

как Adm объявлен?
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
  #7  
Старый 07.06.2013, 09:42
Ioanwar Ioanwar вне форума
Прохожий
 
Регистрация: 07.06.2013
Сообщения: 9
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Цитата:
Сообщение от NumLock
как Adm объявлен?

Код:
 Type
  Pac=packed record
    Name,ip,roll:String[255];
  end;
Var
Adm:array of Pac;

Mass на Сервере объявлен так же.
Ответить с цитированием
  #8  
Старый 07.06.2013, 09:48
icWasya icWasya вне форума
Местный
 
Регистрация: 09.11.2010
Сообщения: 499
Репутация: 10
По умолчанию

почему вот так
Код:
ct:=(CS.Socket.ReceiveLength div 4)div 768;

а не вот так
Код:
ct:=CS.Socket.ReceiveLength div sizeof(Adm[0]);
Ответить с цитированием
  #9  
Старый 07.06.2013, 09:57
Ioanwar Ioanwar вне форума
Прохожий
 
Регистрация: 07.06.2013
Сообщения: 9
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Цитата:
Сообщение от icWasya
почему вот так
Код:
ct:=(CS.Socket.ReceiveLength div 4)div 768;

а не вот так
Код:
ct:=CS.Socket.ReceiveLength div sizeof(Adm[0]);
Потому, что в тот момент программа еще не знает, что такое Adm[0]...
Следовательно, что бы мне найти количество элементов в массиве заранее, я делаю так. И следовательно, потом массив принимается точно такой же, и с таким же размером.
Ответить с цитированием
  #10  
Старый 07.06.2013, 10:03
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

ReceiveLength не будет равно количеству переданных байт! сумма нескольких последовательных ReceiveLength будет. и SizeOf(Mass) в отправке лишнее и 4 в приеме.
__________________
Пишу программы за еду.
__________________

Последний раз редактировалось NumLock, 07.06.2013 в 10:08.
Ответить с цитированием
Этот пользователь сказал Спасибо NumLock за это полезное сообщение:
Ioanwar (07.06.2013)
  #11  
Старый 07.06.2013, 10:09
Ioanwar Ioanwar вне форума
Прохожий
 
Регистрация: 07.06.2013
Сообщения: 9
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Цитата:
Сообщение от NumLock
ReceiveLength не будет равно количеству переданных байт! сумма нескольких последовательных ReceiveLength будет. и SizeOf(Mass) в отправке лишнее
Возможно да. Щас проверю отпишусь.
Ответить с цитированием
  #12  
Старый 07.06.2013, 10:13
Ioanwar Ioanwar вне форума
Прохожий
 
Регистрация: 07.06.2013
Сообщения: 9
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Цитата:
Сообщение от NumLock
ReceiveLength не будет равно количеству переданных байт! сумма нескольких последовательных ReceiveLength будет. и SizeOf(Mass) в отправке лишнее и 4 в приеме.
Проверил. В таком случае ошибок нет, но вместо нормальных данных массива приходят только #0#0#0#0#0#0#0#0#0.
Ответить с цитированием
  #13  
Старый 07.06.2013, 10:19
Ioanwar Ioanwar вне форума
Прохожий
 
Регистрация: 07.06.2013
Сообщения: 9
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Цитата:
Сообщение от Ioanwar
Проверил. В таком случае ошибок нет, но вместо нормальных данных массива приходят только #0#0#0#0#0#0#0#0#0.
А нет, это я в ReceiveBuf(Adm[0],Socket.ReceiveLength); поставил ct в место Socket.ReceiveLength когда тестил и забыл убрать))) нафига ставил не знаю)))

NumLock спасибо тебе, вроде работает. Если что отпишусь)
Ответить с цитированием
  #14  
Старый 07.06.2013, 10:23
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

эмуляция передачи данных через сокет. для примера выделения памяти на передающей и принимающей сторонах:
Код:
type
  TMyRec = record
    Id: String[255];
    Name: String[255];
    IP: String[255];
  end;
var
  Arr: array of TMyRec;
  sz: Integer;
  Buffer: Pointer;
begin
  SetLength(Arr, 10); // 10 elements
  Arr[5].Id:='5';
  Arr[5].Name:='NumLock';
  Arr[5].IP:='127.0.0.1';
  sz:=Length(Arr)*SizeOf(TMyRec); // size arr in bytes = element count * size of element
                                  // element size = size of TMyRec
  ShowMessage(IntToStr(sz));

  Buffer:=GetMemory(sz); // get memory for simulate socket (Buffer)
  MoveMemory(Buffer, @Arr[0], sz); // transfer data to "socket"
  SetLength(Arr, 0); // clear source arr




  SetLength(Arr, sz div SizeOf(TMyRec)); // (sz div SizeOf(TMyRec)) how elements?
  MoveMemory(@Arr[0], Buffer, sz); // receive data from "socket", sz .aka. ReceiveLength

  ShowMessage(Arr[5].Id+' '+Arr[5].Name+' '+Arr[5].IP);

  FreeMemory(Buffer);
end;
на реальных сокетах не будет работать потому что передаваемые данные могут и скорее всего будут разбиваться на отдельные пакеты, которые придется складывать в один. хотя для 10 элементов может и сработает, если очень повезет)
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
  #15  
Старый 07.06.2013, 10:34
Ioanwar Ioanwar вне форума
Прохожий
 
Регистрация: 07.06.2013
Сообщения: 9
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Цитата:
Сообщение от NumLock
эмуляция передачи данных через сокет. для примера выделения памяти на передающей и принимающей сторонах:
Код:
type
  TMyRec = record
    Id: String[255];
    Name: String[255];
    IP: String[255];
  end;
var
  Arr: array of TMyRec;
  sz: Integer;
  Buffer: Pointer;
begin
  SetLength(Arr, 10); // 10 elements
  Arr[5].Id:='5';
  Arr[5].Name:='NumLock';
  Arr[5].IP:='127.0.0.1';
  sz:=Length(Arr)*SizeOf(TMyRec); // size arr in bytes = element count * size of element
                                  // element size = size of TMyRec
  ShowMessage(IntToStr(sz));

  Buffer:=GetMemory(sz); // get memory for simulate socket (Buffer)
  MoveMemory(Buffer, @Arr[0], sz); // transfer data to "socket"
  SetLength(Arr, 0); // clear source arr




  SetLength(Arr, sz div SizeOf(TMyRec)); // (sz div SizeOf(TMyRec)) how elements?
  MoveMemory(@Arr[0], Buffer, sz); // receive data from "socket", sz .aka. ReceiveLength

  ShowMessage(Arr[5].Id+' '+Arr[5].Name+' '+Arr[5].IP);

  FreeMemory(Buffer);
end;
на реальных сокетах не будет работать потому что передаваемые данные могут и скорее всего будут разбиваться на отдельные пакеты, которые придется складывать в один. хотя для 10 элементов может и сработает, если очень повезет)
Это интересно, но пока не надо. Сейчас доделаю то что у меня есть, а там буду думать дальше) Разбиваю задачу на много подзадач так сказать.
Теперь могу спокойно поспать, а потом по новой за работу. Спасибо тебе еще раз NumLock.

Последний раз редактировалось Ioanwar, 07.06.2013 в 10:42.
Ответить с цитированием
Ответ


Delphi Sources

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

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 22:39.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter