Indy 写缓冲/高效 TCP 通信

2024-01-01

我知道,我问了很多问题...但作为一名新的 delphi 开发人员,我一直在解决所有这些问题:)

这个使用 indy 10 处理 TCP 通信。为了提高通信效率,我将客户端操作请求编码为单个字节(在大多数情况下,当然后面跟着其他数据字节,但在本例中只有一个字节)。问题是

var Bytes : TBytes;
...
SetLength (Bytes, 1);
Bytes [0] := OpCode;
FConnection.IOHandler.Write (Bytes, 1);
ErrorCode := Connection.IOHandler.ReadByte;

不会立即发送该字节(至少不会调用服务器执行处理程序)。例如,如果我将“1”更改为“9”,则一切正常。我假设 Indy 缓冲传出字节并尝试禁用写入缓冲

FConnection.IOHandler.WriteBufferClose;

但这没有帮助。如何发送单个字节并确保立即发送?而且 - 我在这里添加另一个小问题 - 使用 indy 发送整数的最佳方法是什么?不幸的是我在 TIdTCPServer 的 IOHandler 中找不到像 WriteInteger 这样的函数......并且

WriteLn (IntToStr (SomeIntVal))

对我来说似乎效率不高。我连续使用多个写入命令还是将内容打包在字节数组中并发送一次有什么区别吗?

感谢您的任何答复!

编辑:我添加了一个提示,表明我正在使用 Indy 10,因为读写过程似乎有重大变化。


默认情况下禁用写缓冲。您可以通过测试 fConnection.IOHandler.WriteBufferingActive 属性来检查写入缓冲,以查看它在代码中是否处于活动状态。

至于发送整数的最佳方式......“这取决于”您的协议和总体目标。具体来说,请使用 FConnection.IOHandler.Write(),因为有重载方法可以写入任何类型的数据,包括整数。

取自 IdIOHandler:

// Optimal Extra Methods
//
// These methods are based on the core methods. While they can be
// overridden, they are so simple that it is rare a more optimal method can
// be implemented. Because of this they are not overrideable.
//
//
// Write Methods
//
// Only the ones that have a hope of being better optimized in descendants
// have been marked virtual
procedure Write(const AOut: string; const AEncoding: TIdEncoding = enDefault); overload; virtual;
procedure WriteLn(const AEncoding: TIdEncoding = enDefault); overload;
procedure WriteLn(const AOut: string; const AEncoding: TIdEncoding = enDefault); overload; virtual;
procedure WriteLnRFC(const AOut: string = ''; const AEncoding: TIdEncoding = enDefault); virtual;
procedure Write(AValue: TStrings; AWriteLinesCount: Boolean = False; const AEncoding: TIdEncoding = enDefault); overload; virtual;
procedure Write(AValue: Byte); overload;
procedure Write(AValue: Char; const AEncoding: TIdEncoding = enDefault); overload;
procedure Write(AValue: LongWord; AConvert: Boolean = True); overload;
procedure Write(AValue: LongInt; AConvert: Boolean = True); overload;
procedure Write(AValue: SmallInt; AConvert: Boolean = True); overload;
procedure Write(AValue: Int64; AConvert: Boolean = True); overload;
procedure Write(AStream: TStream; ASize: Int64 = 0; AWriteByteCount: Boolean = False); overload; virtual;

您遇到的另一个问题是“连续使用多个写入命令还是将内容打包在字节数组中并发送一次有什么区别吗?”对于大多数情况来说,是的,这会产生影响。对于压力很大的服务器,您将不得不更多地参与如何来回发送字节,但在这个级别上,您应该将发送抽象为一个单独的协议类型类,该类构建要发送的数据并将其发送到突发并有一个接收协议,该协议接收一堆数据并将其作为一个完整的单元进行处理,而不是将其分解为发送/接收整数、字符、字节数组等。

作为一个非常粗略的快速示例:

TmyCommand = class(TmyProtocol)
private
  fCommand:Integer;
  fParameter:String;
  fDestinationID:String;
  fSourceID:String;
  fWhatever:Integer;
public
  property Command:Integer read fCommand write fCommand;
  ...

  function Serialize;
  procedure Deserialize(Packet:String);
end;

function TmyCommand.Serialize:String;
begin
  //you'll need to delimit these to break them apart on the other side
  result := AddItem(Command) + 
            AddItem(Parameter) + 
            AddItem(DestinationID) + 
            AddItem(SourceID) + 
            AddItem(Whatever);
end; 
procedure TMyCommand.Deserialize(Packet:String);
begin
   Command := StrToInt(StripOutItem(Packet));
   Parameter := StripOutItem(Packet);
   DesintationID := StripOutItem(Packet); 
   SourceID := StripOutItem(Packet);
   Whatever := StrToInt(StripOutItem(Packet));
end;

然后通过以下方式发送:

  FConnection.IOHandler.Write(myCommand.Serialize());

另一边你可以通过 Indy 接收数据,然后

  myCommand.Deserialize(ReceivedData);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Indy 写缓冲/高效 TCP 通信 的相关文章

随机推荐