Форум: "Сети";
Текущий архив: 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.035 c