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

标签 linux performance tcp lazarus indy10

我同时开发了两个软件。

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

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

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

Indy 10 以 1024 字节 block 的形式发送数据,我可以使用 NSLog() 在我的 iOS 应用程序中看到这一点。

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

编辑: 我正在使用以下代码发送 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 不是限制发送数据包大小的工具。当从 TMemoryStream 读取时,其默认缓冲区大小为 32K(请参阅 TIdIOHandler.SendBufferSize 属性)(仅受读取时可用内存的限制),然后传递任意多个字节被读取到底层套接字以进行发送。

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 的限制。确保您的 iOS 应用在从 stream 事件处理程序中的 NSInputStream 读取时未将其输入缓冲区限制为 1024 字节。

关于linux - Indy 10 以 1024 个 block 发送数据。如何增加 block 大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32999006/

相关文章:

java.net.InetAddress java 类不解析 Alpine Docker 容器上的 IP

sql - 两个查询,一个使用 OR,一个使用 IN(),是否具有相同的性能?

mysql - 了解 MySQL 解释, `rows` -wise

c - arc4random_buf 是否有最佳批量大小?

c - 未知的段错误

c# - 暂时锁定端口以供测试

python - 带有 Scapy 的不需要的 RST TCP 数据包

c++ - 如何正确杀死 fork 之子

linux - 在 darwin for linux 上交叉编译 CGO 应用程序

linux - 提取大括号之间的文本