Solved

send receive TMemorystream over UDP

Posted on 2008-10-21
8
1,787 Views
Last Modified: 2013-11-23
hi all,

i trying like to porting my software that was compiled by delphi 6 to delphi 2007;
unfortunately, i can't found the subtitute for nmUDP (netmaster) component which have methode :
readstream, and sendstream  of Tmemorystream.
 
would you like to write some example code(methode) for sender and listener:
1. using UDP
2. send a TMEmorystream
3. the listener (aSocket or whatever) can receive data as a Tmemorystream or processed to be TMemory stream.

4.  whatever the component(indy, ics, synapse, etc...) used as long it's work on delphi 2007, it's ok

thanks
0
Comment
Question by:pete_03
  • 3
  • 3
  • 2
8 Comments
 
LVL 17

Expert Comment

by:TheRealLoki
ID: 22771800
with Indy you'd use SendBuffer(Buffer, count) and Read(Buffer, count_)

here's a very simple example I wrote using a TStringStream...
using a TMemoryStream is similar, but a stringstream is easier to demonstrate

procedure TForm1.eSendKeyPress(Sender: TObject; var Key: Char);
var
  s: string;
  Buffer: Array [0..maxBufferSize] of Byte;
  count: Integer;
  stream: TStringStream;
begin
  if ord(Key) = vk_Return then
  begin
    Key := #0;
// now send this
 
    s := eSend.Text;
 
    IdUDPClient1.Host := 'localhost';
    IdUDPClient1.Port := StrToIntDef(eClientPort.Text, 1234);
 
    stream := TStringStream.Create(S);
 
    stream.Seek(0, soFromBeginning);
    stream.Read(Buffer, Stream.Size);
    IdUDPClient1.SendBuffer(Buffer, stream.size);
 
// you can also use the methof below
// or of course you can just use IdUDPClient1.Send(AData: string)
{
    s := eSend.Text;
    count := length(s);
    move(s[1], Buffer, count);
    IdUDPClient1.Host := 'localhost';
    IdUDPClient1.Port := StrToIntDef(eClientPort.Text, 1234);
    IdUDPClient1.SendBuffer(Buffer, count);
}
  end;
end;

Open in new window

0
 

Author Comment

by:pete_03
ID: 22772131
thanks for reply, i am beginner of delphi, could wrap that code to a methode like:
procedure sendstream(aMemoryStream: TMemorystream) as easy as : nmUDP1.sendstream(myMemorystream)

and how about the listener ?
0
 
LVL 17

Expert Comment

by:TheRealLoki
ID: 22772713
show me your exact example of what you ant (i.e. your nmUDP code)
and I will show you how to do the equivalent in Indy.
The bit I need to understand is if you need to send the "size" of the stream first, or if you do not need the size
0
Is Your AD Toolbox Looking More Like a Toybox?

Managing Active Directory can get complicated.  Often, the native tools for managing AD are just not up to the task.  The largest Active Directory installations in the world have relied on one tool to manage their day-to-day administration tasks: Hyena. Start your trial today.

 

Author Comment

by:pete_03
ID: 22772762
procedure TMainModule.SendRecordValue(FRemoteHost: String; FPort: Integer);
var FMemoryStream: TMemoryStream;
    i : Byte;
    FValue : Single;
begin
   FMemoryStream := TMemoryStream.Create;
   try;
      for i := 0 to (record.Count-1) do
      begin
        FValue := record.Value[i];
        FMemoryStream.Write(FValue, SizeOf(FValue));
      end;

      NMUDP1.RemoteHost := FRemoteHost;
      NMUDP1.RemotePort := FPort;
      NMUDP1.SendStream(FMemoryStream);

   finally
      FMemoryStream.Free;
   end;
end;






procedure TfrmMonitoring.NMUDP1DataReceived(Sender: TComponent;
  NumberBytes: Integer; FromIP: String; Port: Integer);
var
    FMemoryStream : TMemoryStream;
    FValue : Single;
    I : Integer;
begin
   if NumberBytes > 0 then
   begin
      FByteReceived := FByteReceived + NumberBytes;
      FMemoryStream := TMemoryStream.Create;
      try
         NMUDP1.ReadStream(FMemoryStream);
         FMemoryStream.Position := 0;
         i := 0;
         repeat
            FMemoryStream.Read(FValue, SizeOf(FValue));
            ClientRecord.Value[i] := FValue;
            Inc(i);
         until (FMemoryStream.Position >= FMemoryStream.Size);
      finally
         FMemoryStream.Free;
      end;
   end;

0
 
LVL 37

Expert Comment

by:Geert Gruwez
ID: 22773907
I mostly use a TStringList to send strings ...

you may need to check if ClientRecord.RecordCount works

procedure TForm1.SendRecordValue(aRemoteHost: String; aPort: Integer);
var i : Byte;
    List: TStringList;
begin
  List := TStringList.Create;
  try
    for i := 0 to (record.Count-1) do
      List.Add(Record.Value[i]);
    IdUDPClient1.Send(aRemoteHost, aPort, List.Text);
  finally
    List.Free;
  end;
end;
 
procedure TForm1.IdUDPServer1UDPRead(Sender: TObject; AData: TStream;
  ABinding: TIdSocketHandle);
var
  I : Integer;
  List: TStringList;
  Stream: TStringStream;
begin
  ClientRecord.RecordCount := 0;
  if AData.Size > 0 then
  begin
    List := TStringList.Create;
    try
      Stream := TStringStream.Create('');
      try
        Stream.CopyFrom(AData, AData.Size);
        List.Text := Stream.DataString;
      finally
        Stream.Free;
      end;
      ClientRecord.RecordCount := List.Count;
      for I := 0 to List.Count - 1 do
        ClientRecord.Value[i] := List[I];
    finally
      List.Free;
    end;
  end;
end;

Open in new window

0
 

Author Comment

by:pete_03
ID: 22775029
on idUDP server, i doubleclick at onUDPRead Event then on editor:
procedure TForm1.IdUDPServer1UDPRead(Sender: TObject; AData: TBytes;
  ABinding: TIdSocketHandle);


procedure TForm1.IdUDPServer1UDPRead(Sender: TObject; AData: TStream;
  ABinding: TIdSocketHandle);

it's raises error, the parameters AData should be Tbytes instead TStream.
then i forced to change the parameters type to TStream as you suggest, application compiled successfully, i set a breakpoint  at this event, nothing fired when the client has sent a udp packet?


i am using indy10, D2007 default packages
0
 
LVL 37

Expert Comment

by:Geert Gruwez
ID: 22775544
oops, that was for Delphi 7

this is for Delphi 2007
procedure TForm1.IdUDPServer1UDPRead(Sender: TObject; AData: TBytes; ABinding: TIdSocketHandle);
var
  I : Integer;
  List: TStringList;
  Stream: TStringStream;
begin
  //ClientRecord.RecordCount := 0;
  if Length(AData) > 0 then
  begin
    List := TStringList.Create;
    try
      Stream := TStringStream.Create('');
      try
        Stream.Read(AData, Length(AData));
        List.Text :=  Stream.DataString;
        ClientRecord.RecordCount := List.Count;
        for I := 0 to List.Count - 1 do
          ClientRecord.Value[i] := List[I];
      finally
        Stream.Free;
      end;
    finally
      List.Free;
    end;
  end;
end;
 
procedure TForm1.SendRecordValue(aRemoteHost: String; aPort: Integer);
var i : Byte;
    List: TStringList;
begin
  List := TStringList.Create;
  try
    for i := 0 to (record.Count-1) do
      List.Add(Record.Value[i]);
    IdUDPClient1.Host := aRemoteHost;
    IdUDPClient1.Port := aPort;
    IdUDPClient1.Send(List.Text);
  finally
    List.Free;
  end;
end;

Open in new window

0
 
LVL 17

Accepted Solution

by:
TheRealLoki earned 125 total points
ID: 22801368
ok, that's all pretty easy
as requested, using your code, I have just added the few things you need

procedure UDPSendStream(UDP_: TIdUDPClient; stream: TStream);
const
  maxBufferSize = 8192; // just make sure this is bigger than you ever need...you can loop but dont know if you need that in your situation
var
  Buffer: Array [0..maxBufferSize] of Byte;
  count: Integer;
begin
  stream.Seek(0, soFromBeginning);
  stream.Read(Buffer, Stream.Size);
  UDP_.SendBuffer(Buffer, stream.size);
end;
 
 
var FMemoryStream: TMemoryStream;
    i : Byte;
    FValue : Single;
begin
   FMemoryStream := TMemoryStream.Create;
   try
      for i := 0 to (record_.Count-1) do
      begin
        FValue := record_.Value[i];
        FMemoryStream.Write(FValue, SizeOf(FValue));
      end;
 
      IdUDPClient1.Host := FRemoteHost;
      IdUDPClient1.Port := FPort;
      UDPSendStream(IdUDPClient1, FMemoryStream);
   finally
      FMemoryStream.Free;
   end;
end;
 
 
procedure TForm1.IdUDPServer2UDPRead(Sender: TObject; AData: TStream; ABinding: TIdSocketHandle);
var
    FMemoryStream : TMemoryStream;
    FValue : Single;
    I : Integer;
begin
   if NumberBytes > 0 then
   begin
      FByteReceived := FByteReceived + NumberBytes;
      FMemoryStream := TMemoryStream.Create;
      try
         FMemoryStream.CopyFrom(AData, AData.Size);
         FMemoryStream.Position := 0;
         i := 0;
         repeat
            FMemoryStream.Read(FValue, SizeOf(FValue));
            ClientRecord.Value[i] := FValue;
            Inc(i);
         until (FMemoryStream.Position >= FMemoryStream.Size);
      finally
         FMemoryStream.Free;
      end;
   end;
end;

Open in new window

0

Featured Post

3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Working with hours 3 57
java. non-English characters encoding problem. intellij idea 3 83
LAN or WAN ? 11 90
JAudiorecorder record freezing the app 29 67
The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Here is a helpful source code for C++ Builder programmers that allows you to manage and manipulate HTML content from C++ code, while also handling HTML events like onclick, onmouseover, ... Some objects defined and used in this source include: …
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
The viewer will learn how to synchronize PHP projects with a remote server in NetBeans IDE 8.0 for Windows.

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question