Question

I am trying to exchange data between a IdTCPServer and an IdTCPClient using a collection that I convert to a stream before I send it over the network. Unfortunately, no matter how I try, I can't seem to pass the stream between the client and the server. The code always hangs on the IdTCPClient1.IOHandler.ReadStream(myStream, -1, True) line.

The relevant portion of my code is shown below:

Client side

  with ClientDataModule do
  begin
    try
      try
        intStreamSize := StrToInt(IdTCPClient1.IOHandler.ReadLn); // Read stream size
        IdTCPClient1.IOHandler.ReadStream(myStream, -1, True);  // Read record stream
      finally
        ReadCollectionFromStream(TCustomer, myStream);
      end;
    except
      ShowMessage('Unable to read the record from stream');
    end;
  end;

Server side

    try
      try
        SaveCollectionToStream(ACustomer, MStream);
      finally
        MStream.Seek(0, soFromBeginning);
        IOHandler.WriteLn(IntToStr(MStream.Size));   // Send stream size
        IOHandler.Write(MStream, 0);        // Send record stream
      end;
    except
      ShowMessage('Unable to save the record to stream');
    end;

I would greatly appreciate your assistance with solving this problem.

Thanks,

JDaniel

Était-ce utile?

La solution

You are setting the AReadUntilDisconnect parameter of ReadStream() to True, which tells it to keep reading until the connection is closed. You need to set the parameter to False instead. You also need to pass in the stream size in the AByteCount parameter, since you are sending the stream size separately so you have to tell ReadStream() how much to actually read.

Try this:

Client:

with ClientDataModule do
begin
  try
    intStreamSize := StrToInt(IdTCPClient1.IOHandler.ReadLn);
    IdTCPClient1.IOHandler.ReadStream(myStream, intStreamSize, False);
    myStream.Position := 0;
    ReadCollectionFromStream(TCustomer, myStream);
  except
    ShowMessage('Unable to read the record from stream');
  end;
end;

Server:

try
  SaveCollectionToStream(ACustomer, MStream);
  MStream.Position := 0;
  IOHandler.WriteLn(IntToStr(MStream.Size));
  IOHandler.Write(MStream);
except
  ShowMessage('Unable to save the record to stream');
end;

If you can change your protocol, then you can let Write() and ReadStream() exchange the stream size internally for you, like this:

Client:

with ClientDataModule do
begin
  try
    // set to True to receive a 64bit stream size
    // set to False to receive a 32bit stream stream
    IdTCPClient1.IOHandler.LargeStream := ...;

    IdTCPClient1.IOHandler.ReadStream(myStream, -1, True);
    myStream.Position := 0;
    ReadCollectionFromStream(TCustomer, myStream);
  except
    ShowMessage('Unable to read the record from stream');
  end;
end;

Server:

try
  SaveCollectionToStream(ACustomer, MStream);
  MStream.Position := 0;

  // set to True to send a 64bit stream size
  // set to False to send a 32bit stream stream
  IOHandler.LargeStream := ...;

  IOHandler.Write(MStream, 0, True);
except
  ShowMessage('Unable to save the record to stream');
end;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top