Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2004.08.01;
Скачать: [xml.tar.bz2];

Вниз

Пересылка массива данных типа float через Socket   Найти похожие ветки 

 
samalex2504   (2004-05-27 11:02) [0]

Уважаемые знатоки!!!
Есть необходимость рассылыть массивы двойной размерности [integer, float] пользователям по локальной сети. Я думаю делать это при помощи компонет ServerSocket и ClientSocket. Можно сделать это при помощи
 For i := 0 to ServerSocket1.Socket.ActiveConnections-1 do
 begin
   ServerSocket1.Socket.Connections[i].SendText(PrStringList.Text);
 end;
где PrStringList это данные в текстовом виде.
Но хотелось бы передавать float без перевода в текстовую форму.
Если у кого есть примеры, вышлите пожалуйста ...


 
Digitman ©   (2004-05-27 11:14) [1]

var
 ms: TStream;
 FloatArray: array[..] of Double;
 IntArray: array[..] of Integer;

...

ms := TMemoryStream.Create;
ms.WriteBuffer(FloatArray, SizeOf(FloatArray));
ms.WriteBuffer(IntArray, SizeOf(IntArray));
ms.Position := 0;
..
Socket.SendStream(ms);


 
samalex2504   (2004-05-27 11:41) [2]

Digitman ©  
Это отправляющая часть, а принимающая?


 
Digitman ©   (2004-05-27 12:03) [3]

а принимающая - ReceiveBuf()

var
ms: TStream;
FloatArray: array[..] of Double;
IntArray: array[..] of Integer;
p: PByte;
BytesRead, BytesNeed: Integer;
...

p := @FloatArray;
BytesNeed := SizeOf(FloatArray);

while BytesNeed >0 do
begin
  BytesRead := Socket.ReceiveBuf(p^, BytesNeed);
  Dec(BytesNeed, BytesRead);
  Inc(p, BytesRead);
end;

p := @IntArray;
BytesNeed := SizeOf(IntArray);

while BytesNeed >0 do
begin
  BytesRead := Socket.ReceiveBuf(p^, BytesNeed);
  Dec(BytesNeed, BytesRead);
  Inc(p, BytesRead);
end;


 
Digitman ©   (2004-05-27 12:19) [4]

все гениальное просто)

общий примерный случай (для асинхр.неблок. режима) :

var
ValueOfSomeType: TSomeType;
p: PByte;
BytesNeed: Integer;
...

//принимаем данные в переменную ValueOfSomeType

p := @FloatArray;
BytesNeed := SizeOf(ValueOfSomeType);
while BytesNeed > 0 do
 Application.ProcessMessages;

...

//
procedure TSomeObject.SomeSocketRead(..);
var
 BytesRead: Integer;
begin

if BytesNeed > 0 then
begin
 BytesRead := Socket.ReceiveBuf(p^, BytesNeed);
 Dec(BytesNeed, BytesRead);
 Inc(p, BytesRead);
end;


 
samalex2504   (2004-05-27 16:21) [5]

Я расслылающую часть
организовал при помощи ServerSocket.

var
 Data_Send : array of Double;
 IdMeas_Send : array of Integer;
begin

 SetLength(Data_Send,SizePoint);
 SetLength(IdMeas_Send,SizePoint);

 ...
 Заполнение массивов
 ...

 ms := TMemoryStream.Create;

 ms.WriteBuffer(Data_Send, SizeOf(Data_Send));
 ms.WriteBuffer(IdMeas_Send, SizeOf(IdMeas_Send));
 ms.Position:=0;

 For i := 0 to ServerSocket1.Socket.ActiveConnections-1 do
 begin
   ServerSocket1.Socket.Connections[i].SendStream(ms);
 end;

 ms.Destroy;

end;

*****************************************************

Принимающую при помощи ClientSocket.
А ReceiveBuf() ... вставил в событие OnRead.

procedure TF_Menu00.ClientSocket1Read(Sender: TObject;
 Socket: TCustomWinSocket);
var
 ms: TStream;
 p: PByte;
 BytesRead, BytesNeed: Integer;
 Data_Send : array of Double;
 IdMeas_Send : array of Integer;

begin
 SetLength(Data_Send,SizeAllPoint);
 SetLength(IdMeas_Send,SizeAllPoint);

 p := @Data_Send;
 BytesNeed := SizeOf(Data_Send);

 while BytesNeed >0 do
 begin
   BytesRead := Socket.ReceiveBuf(p^, BytesNeed);
   Dec(BytesNeed, BytesRead);
   Inc(p, BytesRead);
 end;

 p := @IdMeas_Send;
 BytesNeed := SizeOf(IdMeas_Send);

 while BytesNeed >0 do
 begin
   BytesRead := Socket.ReceiveBuf(p^, BytesNeed);
   Dec(BytesNeed, BytesRead);
   Inc(p, BytesRead);
 end;
end;

*******************************************************
При обработке OnRead выдается ошибка "Access violation on adress ..."


 
Palladin ©   (2004-05-28 04:21) [6]


>  BytesNeed := SizeOf(Data_Send);

Замечательно. В итоге всегда 4.


>  BytesNeed := SizeOf(IdMeas_Send);

Та же лажа...


> p := @Data_Send;

Круто.


> Socket.ReceiveBuf(p^, BytesNeed);

Просто умопомрачительно.

Ну и так далее в таком же духе...

Изучи работу с динамическими массивами. Что это такое и как с этим обращатся.


 
Digitman ©   (2004-05-28 08:56) [7]


> samalex2504   (27.05.04 16:21) [5]


см. [6]

ты, видимо, на самом деле не видишь  разницу между статическим и динамическим массивом

кр.того, цикл

For i := 0 to ServerSocket1.Socket.ActiveConnections-1 do
begin
  ServerSocket1.Socket.Connections[i].SendStream(ms);
end;

неверен по логике

открывай в справке описание метода SendStream() и вникай в каждую фразу


 
samalex2504   (2004-05-28 11:08) [8]

Digitman, Palladin
Виноват, SizeOf(Data_Send) - переделал Data_Send, IdMeas_Send на статическиt массивы.

SendStream() - справку прочитал очень внимательно. В общем, она небольшая

**********************************
Declaration
procedure SendStream(MainStream: TStream);

Description
The SendStream method sends the contents of a stream to the remote host.

Parameters:
MainStream = The MainStream parameter specifies the stream that contains the data that is to be sent to the remote host. MainStream must contain a valid stream.
*******************************


 
Digitman ©   (2004-05-28 11:25) [9]


> переделал Data_Send, IdMeas_Send на статические массивы


ну переделал и переделал ... хотя ничто не ограничивает тебя использовать и дин. массивы для этой цели)


> справку прочитал очень внимательно. В общем, она небольшая


что-то я не понял, это откуда такой хэлп взялся ?
у меня в Д5 описание метода выглядит вот так:

Writes all the information that can be read from the AStream parameter to the socket connection.

function SendStream(AStream: TStream): Boolean;

Description

Use SendStream to write to the socket connection. The writing may occur in the OnSocketEvent event handler of a Windows socket object or in the OnWrite or OnClientWrite event handler of a socket component. Alternately, SendStream may write from a socket that is expected to write to the connection without a notification to signal the connection’s readiness to read. SendStream reads information from the stream indicated by AStream and writes it to the socket connection. The value returned by SendStream indicates whether any information was successfully written to the connection.

Note: The Stream passed as a parameter to SendStream becomes “owned” by the windows socket object.  The Windows socket object frees the stream when it is finished with it.  Do not attempt to free the stream after it has been passed as a parameter.

Подчеркнутое весьма важно ! Сравни это со своим кодом - поймешь свою ошибку


 
samalex2504   (2004-05-28 13:10) [10]

Digitman ©  
Я так понял, что если один раз сделал SendStream(ms), то поток ms очищается. И что мне делать? Каждый раз записывать данные в поток или пользоваться другими методами?


 
Digitman ©   (2004-05-28 13:30) [11]


> Я так понял, что если один раз сделал SendStream(ms), то
> поток ms очищается


не правильно ты понял... после успешной передачи поток не что очищается - он вообще уничтожается, т.е. сам TStream-объект уничтожается автоматически в недрах SensStream-метода ..

т.е.вызвав SendStream с параметром-объектом класса TStream, ты автоматически делегируешь объекту класса TCustomWinSocket монопольное право на уничтожение этого объекта-потока, и посему ты уже не вправе уничтожать объект-поток самостоятельно - это уже епархия того объекта, чей метод SendStream ты вызвал..

впрочем, нет никаких ограничений на возможность изменять позиционирование и тек.содержимое передаваемого в наст.момент потока - это можно сделать в любой момент времени, пока объект-поток не уничтоже (т.е. еще существует  реально)


> что мне делать? Каждый раз записывать данные в поток или
> пользоваться другими методами?


для каждого клиента, которому требуется передать инф-цию методом SendStream(), создавать отдельный объект-поток


 
samalex2504   (2004-05-28 15:02) [12]

Digitman ©  
Да, действительно, я убрал ms.Destroy, создал для каждого подключения свой поток ms[i]. Не нашел только в помощи, как определять успешность передачи. Поставил
  try
     ServerSocket1.Socket.Connections[i].SendStream(ms[i]);
   except
     Memo2.Lines.Add("Error send to "+IntToStr(i));
     ms[i].Destroy;
   end;

Глючит приемная часть, я ее описал в п.5, только на массивы статические поменял той же размерности, зависает ...


 
Sunny Way   (2004-05-28 18:02) [13]

Предлагаю немного другой вариант чтения данных у сервера

const FTimeOut = 6000;

var WorkSocket: TCustomWinSocket; //глобальная перем.

procedure TSomeServer.OnClientRead(Sender: TObject;
 Socket: TCustomWinSocket);
var double_array: array of double;
  integer_array: array of integer;
  count: integer; //
  p,pMem: pbyte;
  i, res,bytes_need: integer;
begin
 WorkSocket := Socket; //для работы с ним в другим функциях

 count := 3; // видимо глобальная перем.

 // читаем double
 setlength(double_array, count);
 bytes_need := count*sizeof(double);
 getmem(pMem,bytes_need);
 try
   p := pMem;
   res := ReadSocketData(p, bytes_need);
   if res <> bytes_need then exit;{или что-нибудь там}
   for i := 0 to count - 1 do
   begin
      move(p^, double_array[i], sizeof(double));
      inc(p,sizeof(double)) ;
   end;
 finally
    freemem(pMem);
 end;

 // читаем integer
 setlength(integer_array, count);
 bytes_need := count*sizeof(integer);
 getmem(pMem, bytes_need);
 try
   p := pMem;
   res := ReadSocketData(p, bytes_need);
   if res <> bytes_need then exit;{или что-нибудь тут}
   for i := 0 to count - 1 do
   begin
      move(p^, integer_array[i], sizeof(integer));
      inc(p,sizeof(integer)) ;
   end;
 finally
    freemem(pMem);
 end;
end;

{----------------- ReadSocketData --------------}
{читает любые данные по TimeOut, которые в TServerSocket забыли вставить (если работать в режиме non-blocking)}

function TDCMStore_Server.ReadSocketData(var p: pbyte; size: integer):integer;
const delay = 10; // задержка в милисекундах
var
 TimeCnt: Word;
 Buf: pByte;
 Buf_Count: Integer;
 current_size: integer;
begin
 TimeCnt := 0;
 current_size := size;
 Buf := p;
 zeromemory(p, size);
 with WorkSocket do
   while TimeCnt < (FTimeOut/delay) do
   begin
     Buf_Count := ReceiveBuf(Buf^, current_size);
     if Buf_Count > 0 then
     begin
       TimeCnt := 0;
       dec(current_size, buf_count);
       if current_size < 1 then break;
       inc(Buf, buf_count);
     end
     else begin
       sleep(delay);
       Inc(TimeCnt);
     end;
   end;
 Result := size - current_size;
end;

Может покажется немного сложновато :).


 
samalex2504   (2004-05-31 14:09) [14]

Sunny Way  
ClientType кокой ставить: ctNonBlocking или ctBlocking?


 
Digitman ©   (2004-05-31 14:17) [15]

см.
http://delphimaster.net/view/6-1085955124/


 
Sunny Way ©   (2004-06-02 14:23) [16]

Интересно, а удалось ли тебе использовать мой пример работы сервера?


 
Verg ©   (2004-06-02 20:29) [17]

Посмотри примерчик, может внесет ясность:

http://webfile.ru/16343



Страницы: 1 вся ветка

Форум: "Сети";
Текущий архив: 2004.08.01;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.036 c
6-1085985936
Micah'GF
2004-05-31 10:45
2004.08.01
Winsock: recv постоянно возвращает 65535


1-1090237538
ruslan
2004-07-19 15:45
2004.08.01
Rezidentnaya proqramma


14-1089885307
Artem123
2004-07-15 13:55
2004.08.01
как вставить запись в таблицу из DBGrid и ....


14-1089455445
guest_Dmitry
2004-07-10 14:30
2004.08.01
Подскажите, как избавиться


14-1089600249
Думкин
2004-07-12 06:44
2004.08.01
С днем рождения! 12 июля





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский