I found Remy Lebeau to demonstrate IdTCP components in XE2, and I wanted to play a little with it. (You can find it here ) I would like to send an image using these components, and the best approach seems to be using TMemoryStream. If I send lines, the connection works fine, the lines are transmitted successfully, however, when I change it to Stream, it does not work. Here is the code:
Server
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('<ServerExec> '+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;
Client
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;
When I try to send a stream from the client, nothing observable happens (the breakpoint in OnExecute does not work). However, when you close the programs (after sending the MemoryStream), two things happen:
- If the client is closed first, only after that the
except part is processed (the log shows the โFailed to receiveโ error. However, even if I put a breakpoint on the first line of the try-except block, it is somehow skipped and only the error is displayed). - If the server is closed first, the IDE does not return back from debugging, the Client does not change its state to disconnected (as usual, when the server shuts down), and after the Client is closed, an access violation gives an error from the Server application. I assume this means that there is a server thread that is still running and maintaining the connection. But no matter how much time I give him, he never completes the task of getting a MemoryStream.
Note. The server uses IdSchedulerOfThreadDefault and IdAntiFreeze , if that matters.
Since I cannot find a reliable source of help for the updated Indy 10 (all this seems to refer to the earlier Indy 10 or even Indy 9), I hope you can tell me what is wrong. Thanks
- ANSWER -
SERVER
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;
CUSTOMER
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;