套接字选项SO_SNDLOWAT的用途是什么

时间:2011-11-23 16:46:37

标签: linux sockets unix porting

我目前正在使用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的插座网络API,Bill Fenner,Andrew M. Rudoff ”一书中找到了

      

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

    我明白,如果我想在套接字缓冲区中写入(无论我写的是什么大小),缓冲区需要至少SO_SNDLOWAT个字节空闲。

  3. 我不知道该怎么做SO_SNDLOWAT

3 个答案:

答案 0 :(得分:2)

正如您所看到的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之间的任何值,只需记住,SO_SNDLOWAT的默认值是1,这也是非阻塞套接字的默认行为(它必须接受至少1个字节或失败{{1 }})

    请注意,UDP套接字总是全有或全无,它们永远不会只接受#34;部分数据",因此设置EWOULDBLOCK仅与TCP套接字相关,只接受部分提供的数据。

  2. 如果套接字阻塞,设置SO_SNDLOWATSO_SNDLOWAT调用没有实际影响,因为在这种情况下套接字将始终接受所有数据或它将阻止然后它将阻止,直到所有数据都被接受或命中发送超时(如果已使用send()设置发送超时或基础协议有自己的发送超时)。

  3. 无论套接字是否阻塞,无论是UDP还是TCP,SO_SNDTIMEOpoll()调用只会声称此套接字是可写的,如果至少为{{ {}}} {}

  4. 可以接受1}}个字节。

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

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

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

  

SO_SNDLOWAT在Linux上无法更改。 setsockopt失败了   错误ENOPROTOOPT