使用IdTCPClient和IdTCPServer发送和接收TMemoryStream [英] Sending and receiving a TMemoryStream using IdTCPClient and IdTCPServer

查看:502
本文介绍了使用IdTCPClient和IdTCPServer发送和接收TMemoryStream的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在XE2中找到了雷米·勒博(Remy Lebeau)的IdTCP组件的聊天演示,我想稍微玩一下。 (可以在此处找到)我想发送一个使用这些组件的图片,最好的方法似乎是使用TMemoryStream。如果我发送字符串,则连接工作正常,字符串成功传输,但是当我将其更改为Stream时,它将无法正常工作。这是代码:

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 here) 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:

服务器

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之后),发生两件事:

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:


  • 如果首先关闭了客户端,则只有在关闭客户端后, except 部分得到处理(日志显示无法接收错误。但是,即使我在try-except块的第一行上放置了一个断点,它也会以某种方式出现将被跳过,仅显示错误。)

  • 如果首先关闭服务器,则IDE不会从 debug 变回原来的状态,客户端也不会变其状态为 disconnected (断开服务器时通常会发生这种情况),并且在关闭客户端后,也会出现服务器应用中的访问冲突错误。我猜这意味着服务器的一个线程仍在运行并维护连接。但是,无论我花多少时间,它都永远不会完成接收MemoryStream的任务。

  • If the Client is closed first, only then does the except 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).
  • If the Server is closed first, the IDE doesn't change back from debug, Client doesn't change its state to disconnected (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.

注意:服务器使用 IdSchedulerOfThreadDefault IdAntiFreeze ,如果这很重要。

Note: The server uses IdSchedulerOfThreadDefault and IdAntiFreeze, if that matters.

找不到经过改进的Indy 10的任何可靠的帮助源(所有这些似乎都适用于较旧的Indy 10甚至Indy 9),我希望您能告诉我哪里出了问题。谢谢

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

-答案-

服务器

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;


推荐答案

只需使用适当的参数:

.IOHandler.Write(ms, 0, true); //true ... indicates WriteByteCount

.IOHandler.ReadStream(ms, -1); //-1 ... use ByteCount

这篇关于使用IdTCPClient和IdTCPServer发送和接收TMemoryStream的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆