【问题标题】:What's the purpose of the socket option SO_SNDLOWAT套接字选项 SO_SNDLOWAT 的目的是什么
【发布时间】:2012-01-04 23:11:27
【问题描述】:

我目前正在将一个 C 语言软件从 Tru64 移植到 Linux Suse 11。 在 Tru64 上,他们将SO_SNDLOWAT 套接字选项的值设置为1024 * 64。在 Linux 上,此选项不可更改,其值为 1。

我想弄清楚,不将SO_SNDLOWAT 设置为1024 * 64 对Linux 上的软件执行会有什么影响。

问题是我发现SO_SNDLOWAT的目的有两个定义(解释):

  1. 在 Linux 上的 socket 手册页上找到:

    SO_SNDLOWAT
    指定缓冲区中的最小字节数,直到 套接字层将数据传递给协议

    我知道它指定了缓冲区中要继续的最小字节数(在这种情况下用于发送消息)。缓冲区至少需要填充SO_SNDLOWAT 字节才能继续

  2. 在《UNIX 网络编程:W. Richard Stevens、Bill Fenner、Andrew M. Rudoff 的套接字网络 API》一书中找到

    发送低水位标记是套接字发送缓冲区中必须存在的可用空间量,以便 select 返回“可写”。

    我明白,如果我想写入套接字缓冲区(无论我正在写入的大小),缓冲区至少需要有 SO_SNDLOWAT 字节可用。

我不知道如何看待SO_SNDLOWAT

【问题讨论】:

    标签: linux sockets unix porting


    【解决方案1】:

    您可以看到at this question,它涵盖了其他套接字选项,答案取决于操作系统,因此两个答案可能都是正确的,因为一个是来自 Linux 世界的答案,一个是来自 UNIX(BSD和 Co) 世界。

    在 BSD 和 BSD 克隆中,此选项的含义如下:

    1. 如果套接字是非阻塞并且您调用send(),它必须能够同时接受所有提供的数据或至少接受SO_SNDLOWAT字节的数据;如果这是不可能的,它将不接受任何数据并且send() 失败并出现错误。

      因此,如果您将SO_SNDLOWAT 设置为 100 并尝试发送 50 个字节,它将发送 50 个字节或什么也不发送。如果您将SO_SNDLOWAT 设置为 100 并尝试发送 200 个字节,它必须至少接受 100 个字节的数据,它可以接受更多,最多可以接受整个 200 个字节,以及 100 和 200 之间的任何值,不能少于大于 100。请记住,SO_SNDLOWAT 的默认值是 1,这也是非阻塞套接字的默认行为(它必须接受至少 1 个字节,否则会因EWOULDBLOCK 而失败)

      请注意,UDP 套接字总是全有或全无,它们从不只接受“部分数据”,因此设置SO_SNDLOWAT 仅与 TCP 套接字相关,它可能只接受部分数据提供。

    2. 1234563已被接受或发送超时(如果已使用SO_SNDTIMEO 设置发送超时或底层协议有自己的发送超时)。 1234563被send() 调用接受。

    那么这个选项有什么好处呢?通常,它用于避免您的进程在套接字缓冲区已满时以字节为单位提供数据,但与默认行为一样,select()poll() 会说套接字是可写的,即使只有套接字缓冲区中单个字节的空间。换句话说,这只是一种性能优化,因为无论是否设置了SO_SNDLOWAT,以及无论设置为哪个值,在任意套接字写入下都能正常工作的代码都可以正常工作,在某些极端情况下,如果@ 987654340@ 具有合理的价值。但与所有性能调整一样,如果您不确切知道自己在做什么,设置错误的值很容易使事情变得更糟,因此如果有疑问,请不要触摸该设置。

    【讨论】:

      【解决方案2】:

      第一个描述是正确的解释。

      至于无法设置SO_SNDLOWAT 的影响,我认为这并不重要,因为性能取决于诸如 Nagle 的算法、路径 MTU 发现等。我怀疑其他 TCP/IP 实现默默地忽略这个选项。

      【讨论】:

      • 在“链表”的情况下,第二个功能也有意义:如果select 询问套接字是否可写,内核应该在此时分配一个缓冲区并且只返回给应用程序如果可以的话。我可以看到要求保证 send 可以接受至少 n 个字节的好处。
      • 他们是both correct
      【解决方案3】:

      Afaik 第二个是正确的,但我一直无法使用它。

      SO_SNDLOWAT 在 Linux 上不可更改。 setsockopt 失败 错误ENOPROTOOPT

      【讨论】:

      • TCP_NOTSENT_LOWAT 已在内核 2.12 中引入。
      • @Matt 你把TCP_NOTSENT_LOWAT 误认为SO_SNDLOWAT
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-06
      • 2013-01-24
      • 2012-01-22
      • 2010-12-16
      • 2014-04-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多