Indy 10 以 1024 个块发送数据。如何增加块大小?

Indy 10 sends data in 1024 chunks. How to increase chunk size?

我同时开发了两个软件。

一个是iOS设备的TCP客户端,开发于XCode, 另一个是 Linux OS 的 TCP 服务器,它是在 Lazarus 中使用 Indy 10 作为网络框架开发的。

我可以在服务器和客户端之间发送数据,没有大问题, 但是从服务器到客户端的数据传输速度对我来说是个问题。

当从 iOS 客户端向 Linux 服务器发送数据时,我获得了每秒高达 20 MB 的非常好的传输速度, 但是当从 Linux 服务器向 iOS 客户端发送数据时,我每秒最多只能获得一百千字节 (100kb)。

Indy 10 以 1024 字节块发送数据,我可以在我的 iOS 应用程序中使用 NSLog().

看到这一点

问题:如何更改 Indy 10 的行为以一次发送更大的块?

编辑: 我正在使用以下代码发送 TMemoryStream:

procedure TMyClass.SendData(aData: TMemoryStream);
  var i: integer;
      ctx : TIdContext;
begin
  aData.Position := 0;
  with fIdTCP.Contexts.LockList do
  begin
    for i := 0 to Count -1 do //I'm broadcasting the data
    begin
      ctx := TIdContext(Items[i]);
      ctx.Connection.IOHandler.LargeStream:=true;
      ctx.Connection.IOHandler.Write(aData, aData.Size, false);
    end;

    ctx.Connection.IOHandler.WriteBufferClose;
    fIdTCP.Contexts.UnlockList;
  end   
end;

Indy 不是限制发送数据包大小的工具。它的默认缓冲区大小是 32K(参见 TIdIOHandler.SendBufferSize 属性),当从 TMemoryStream 读取时(仅受读取时可用内存的限制)然后将读取的字节数传递给用于发送的底层套接字。

Linux 可能会限制发送的大小。底层套接字的默认发送缓冲区大小可以是 1024 字节。 Linux 文档说明如下:

socket - Linux socket interface

Socket options

The socket options listed below can be set by using setsockopt(2) and read with getsockopt(2) with the socket level set to SOL_SOCKET for all sockets. Unless otherwise noted, optval is a pointer to an int.

...

SO_SNDBUF
Sets or gets the maximum socket send buffer in bytes. The kernel doubles this value (to allow space for bookkeeping overhead) when it is set using setsockopt(2), and this doubled value is returned by getsockopt(2). The default value is set by the /proc/sys/net/core/wmem_default file and the maximum allowed value is set by the /proc/sys/net/core/wmem_max file. The minimum (doubled) value for this option is 2048.

因此请检查您的 Linux 的 wmem_default/wmem_max 配置是否将传输的数据包限制为 1024 字节。

您可以使用 Indy 的 TIdSocketHandle.SetSockOpt() 方法尝试指定不同的缓冲区大小(在 Linux 的配置限制内),例如:

uses
  ..., IdStackConsts;

procedure TMyForm.MyTCPServerConnect(AContext: TIdContext);
var
  BufferSize: Integer;
begin
  BufferSize := ...;
  AContext.Binding.SetSockOpt(Id_SOL_SOCKET, Id_SO_SNDBUF, BufferSize);
  AContext.Binding.GetSockOpt(Id_SOL_SOCKET, Id_SO_SNDBUF, BufferSize);
  // BufferSize now contains the ACTUAL buffer size used by the socket
  // which may be different than what you requested...
end;

如果缓冲区大小没有受到Linux的限制,那么在接收数据时很可能受到iOS的限制。当从 stream 事件处理程序中的 NSInputStream 读取数据时,请确保您的 iOS 应用未将其输入缓冲区限制为 1024 字节。