Indy 10以1024块的形式发送数据.如何增加块大小



我同时开发了两个软件。

One是iOS设备的TCP客户端,使用XCode开发;另一个是Linux操作系统的TCP服务器,使用Indy 10作为网络框架在Lazarus开发。

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

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

Indy 10以1024字节块发送数据,我可以通过使用NSLog()在我的iOS应用中看到这一点。

问题:我如何改变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套接字接口

套接字选项

下面列出的套接字选项可以通过使用setsockopt(2)getsockopt(2)来设置,并将所有套接字的套接字级别设置为SOL_SOCKET。除非另有说明,否则optval是指向int的指针。

SO_SNDBUF
设置或获取以字节为单位的最大套接字发送缓冲区。当使用setsockopt(2)设置该值时,内核将该值加倍(以便为簿记开销留出空间),并且这个加倍的值由getsockopt(2)返回。默认值由/proc/sys/net/core/wmem_default文件设置,最大值由/proc/sys/net/core/wmem_max文件设置。此选项的最小(双倍)值为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字节。

最新更新