title: Sending and receiving a TMemoryStream using IdTCPClient and IdTCPServer
body: <p>I found Remy Lebeau's chat demo of IdTCP components in XE2 and I wanted to play with it a little bit. (It can be found <a href="https://forums.embarcadero.com/thread.jspa?threadID=65247&amp;tstart=105" rel="nofollow">here</a>) I would like to send a picture using these components and the best approach seems to be using TMemoryStream. If I send strings, the connection works fine, the strings are transmitted successfully, however when I change it to Stream instead, it doesn't work. Here is the code:</p>
  
  <p><strong>Server</strong></p>
  
  <pre><code>procedure TMainForm.IdTCPServerExecute(AContext: TIdContext);
  var rcvdMsg: string;
    ms:TMemoryStream;
  begin
  // This commented code is working, it receives and sends strings.
  //  rcvdMsg:=AContext.Connection.IOHandler.ReadLn;
  //  LogMessage('&lt;ServerExec&gt; '+rcvdMsg);
  //
  //  TResponseSync.SendResponse(AContext, rcvdMsg);
    try
      ms:=TMemoryStream.Create;
      AContext.Connection.IOHandler.ReadStream(ms);
  
      ms.SaveToFile('c:\networked.bmp');
    except
      LogMessage('Failed to receive',clred);
    end;
  end;
  </code></pre>
  
  <p><strong>Client</strong></p>
  
  <pre><code>procedure TfrmMain.Button1Click(Sender: TObject);
  var ms: TMemoryStream;
      bmp: TBitmap;
      pic: TPicture;
      s: string;
  begin
    // Again, this code is working for sending strings.
    // s:=edMsg.Text;
    // Client.IOHandler.WriteLn(s);
    ms:=TMemoryStream.Create;
  
    pic:=TPicture.Create;
    pic.LoadFromFile('c:\Back.png');
  
    bmp:=TBitmap.Create;
    bmp.Width:=pic.Width;
    bmp.Height:=pic.Height;
    bmp.Canvas.Draw(0,0,pic.Graphic);
  
    bmp.SaveToStream(ms);
    ms.Position:=0;
    Client.IOHandler.Write(ms);
    ms.Free;
  end;
  </code></pre>
  
  <p>When I try to send the stream from the client, nothing observable happens (breakpoint in the OnExecute doesn't fire). However, when closing the programs(after sending the MemoryStream), two things happen:</p>
  
  <ul>
  <li>If the Client is closed first, only then does the <code>except</code> part get processed (the log displays the 'Failed to receive' error. However, even if I place a breakpoint on the first line of the try-except block, it somehow gets skipped and only the error is displayed).</li>
  <li>If the Server is closed first, the IDE doesn't change back from <em>debug</em>, Client doesn't change its state to <em>disconnected</em> (as it normally does when server disconnects) and after the Client is closed as well, an Access Violation error from the Server app appears. I guess this means that there is a thread of the Server still running and maintaining the connection. But no matter how much time i give it, it never completes the task of receiving the MemoryStream.</li>
  </ul>
  
  <p>Note: The server uses <code>IdSchedulerOfThreadDefault</code> and <code>IdAntiFreeze</code>, if that matters.</p>
  
  <p>As I can't find any reliable source of help for the revamped Indy 10 (it all appears to apply for the older Indy 10, or even Indy 9), I hope you can tell me what is wrong. Thanks</p>
  
  <hr>
  
  <p><strong>- ANSWER -</strong></p>
  
  <p><strong>SERVER</strong></p>
  
  <pre><code>procedure TMainForm.IdTCPServerExecute(AContext: TIdContext);
  var size: integer;
      ms:TMemoryStream;
  begin
    try
      ms:=TMemoryStream.Create;
      size:=AContext.Connection.IOHandler.ReadLongInt;
      AContext.Connection.IOHandler.ReadStream(ms, size);
  
      ms.SaveToFile('c:\networked.bmp');
    except
      LogMessage('Failed to receive',clred);
    end;
  end;
  </code></pre>
  
  <p><strong>CLIENT</strong></p>
  
  <pre><code>procedure TfrmMain.Button1Click(Sender: TObject);
  var ms: TMemoryStream;
      bmp: TBitmap;
      pic: TPicture;
  begin
    ms:=TMemoryStream.Create;
  
    pic:=TPicture.Create;
    pic.LoadFromFile('c:\Back.png');
  
    bmp:=TBitmap.Create;
    bmp.Width:=pic.Width;
    bmp.Height:=pic.Height;
    bmp.Canvas.Draw(0,0,pic.Graphic);
  
    bmp.SaveToStream(ms);
    ms.Position:=0;
    Client.IOHandler.Write(ms, 0, True);
    ms.Free;
  end;
  </code></pre>