在send()(tcp套接字)调用中保证发送的数据的最小大小是多less?

select返回后,写入fd设置为一个TCP套接字。 如果我尝试在该套接字上发送数据,使用send api将一次发送的数据的最小保证大小是多less? 我明白,我必须运行一个循环,以确保所有的数据发送。 不过,我想了解什么是最低保证数据发送,为什么?

从官方的POSIX参考 :

当调用一个输出函数的O_NONBLOCK清除不会被阻塞时,描述符应被认为已准备好写入,不管函数是否能成功传输数据。

正如你所看到的,它实际上并没有提到任何大小,或者写入甚至是成功的,只要你能够写入到socket而不被阻塞。

所以答案是没有最小保证大小。

select() indicates套接字可写时,保证您可以传输至少一个字节而不引起EWOULDBLOCKEAGAIN 。 没什么可说的,你不会招致一个不同的错误:-)

这已经出现了。 我仍然在寻找引用的答案。

让我们从send()的函数原型开始

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

对于阻塞TCP套接字 – 所有的文档将建议send()和write()将返回[1..len]之间的值,除非有错误。 然而,事实是,我所知道的没有人知道send()在成功的情况下返回-1(错误)以外的内容,或者只是“len”,表示所有的“buf”都是在一次调用中发送的。 我从来没有感觉到这一点,所以我防守编码,只是把我的阻塞发送调用循环,直到整个缓冲区发送。

对于非阻塞的TCP套接字 – 您应该就像最小值为“1”(或错误时为-1)一样进行编码。 不要对最小数据大小做任何假设。

对于recv(),你应该总是假设recv()会在成功的情况下返回一个1..len的随机值,或者0(关闭)或者-1(错误)。 不要认为recv会返回一个完整的缓冲区。

我不认为在POSIX层上你有任何控制权。 send()将接受任何你传递给TCP / IP栈实现的内部缓冲区的东西。 接下来会发生什么,它已经是另一个故事,你可以使用相同的select()调用来观看。

如果你问的大小是否适合一个MTU的数据包(但是这个假设在路上也应该小心地使用分组和分组)

UPD:

我会在这里回答你的评论。 不,你根本不应该打扰碎片。 将其留给TCP / IP堆栈。 有很多原因,你不应该这样做。一个作为一个例子。 你的应用程序在OSI模型的Application(7)层上工作(尽管在大多数情况下,我认为OSI模型是一件坏事,它真的适用于这个例子)。 从这个层面,你试图影响更低层次的会话/传输逻辑的功能/属性。 你不应该这样做。 像send(),recv()这样的POSIX调用是为了让你的应用程序能够指示你需要传递一定数量的数据的层,你有一个方法来监视一个命令的执行(select()),这就是所有你必须做的。 而下层则假设尽最大努力传递数据,指导他们根据操作系统网络设置等以最佳方式进行操作。

UPD2:上面的所有内容大多都考虑到了NON_BLOCKING套接字。 抱歉忘了提及这一点,我不使用阻塞套接字在我的项目的年龄..如果你的套接字阻塞我仍然会考虑立即通过一切,只是等待操作结果在另一个线程,例如,因为试图优化这可能会导致非常OS /驱动程序相关的代码。