我在XE2中找到了Remy Lebeau的IdTCP组件聊天演示,我想稍微玩一下。 (可以找到here)我想使用这些组件发送图片,最好的方法似乎是使用TMemoryStream。如果我发送字符串,连接工作正常,字符串传输成功,但是当我将其更改为流时,它不起作用。这是代码:
服务器
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;
客户端
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;
当我尝试从客户端发送流时,没有任何可观察的事件发生(OnExecute中的断点不会触发)。但是,在关闭程序时(发送MemoryStream之后),会发生两件事:
except
部分才会被处理(日志显示'接收失败'错误。但是,即使我在第一行上放置一个断点 - 除了块之外,它会以某种方式被跳过并且只显示错误。)注意:如果重要,服务器会使用IdSchedulerOfThreadDefault
和IdAntiFreeze
。
由于我找不到任何可靠的改造Indy 10的帮助来源(它似乎都适用于较旧的Indy 10,甚至Indy 9),我希望你能告诉我出了什么问题。感谢
- 答案 -
服务器
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;
客户端
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;
答案 0 :(得分:6)
只需使用正确的参数:
.IOHandler.Write(ms, 0, true); //true ... indicates WriteByteCount
.IOHandler.ReadStream(ms, -1); //-1 ... use ByteCount
答案 1 :(得分:3)
预先发送流的大小,以便服务器知道它必须读取多少字节。
服务器:
procedure TMainForm.IdTCPServerExecute(AContext: TIdContext);
var rcvdMsg: string;
ms:TMemoryStream;
size : integer;
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;
try
size := AContext.Connection.IOHandler.ReadLongint;
AContext.Connection.IOHandler.ReadStream(ms, size, false);
ms.SaveToFile('c:\networked.bmp');
finally
ms.Free;
end;
except
LogMessage('Failed to receive',clred);
end;
end;
客户端(固定资源处理)
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;
bmp:=TBitmap.Create;
try
pic.LoadFromFile('c:\Back.png');
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.Size);
Client.IOHandler.Write(ms);
finally
ms.Free;
bmp.Free;
pic.Free;
end;
end;