我几乎总是将send()
用于套接字,现在我转移到WSA
函数。使用send()
,我有一个sendall()
帮助程序,即使在一次尝试中没有发生并且在第一次调用时发生部分发送,也可以确保所有数据都已传送。
因此,在我不必要的时候,不是学习困难的方法或过度复杂的代码,而是决定问你:
阻止
WSASend()
可以发送部分数据还是在返回或失败之前发送所有内容?或者我应该检查发送的字节数与预期发送的字节数并保持不变交付?
ANSWER
:重叠WSASend()
不会发送部分数据,但如果发生,则表示连接已终止。我还没有遇到过这个案子。
答案 0 :(得分:4)
来自WSASend
文档:
如果套接字是非阻塞且面向流的,并且传输缓冲区中没有足够的空间,WSASend将返回,只有部分应用程序的缓冲区已被占用。给定相同的缓冲区情况和阻塞套接字,WSASend将阻塞,直到所有应用程序缓冲区内容都被使用。
我没有尝试过这种行为。顺便说一句,为什么要重写代码才能使用WSA功能?从标准的bsd套接字api切换到基本上使用相同的阻塞行为的套接字对我来说似乎并不是一个好主意。只需将带有send
的旧阻止代码与“重试代码”保持一致,这样便携式和防弹。它不能保存1-2比较,这使得你的IO代码具有高性能。
仅当您尝试利用某些特定于Windows的强度时,或者如果您想要使用WSAWaitForMultipleObjects
比标准select
好一点的非阻塞套接字,请切换到专门的WSA函数但即使在这种情况下,您也可以像我一样使用send
和recv
。
在我看来,使用epoll / kqueue / iocp(或抽象这些文件的库)是套接字的方法。有一些非常基本的任务可以通过阻塞套接字完成,但是如果你越过线并且你需要非阻塞袜子,那么直接切换到epoll / kqueue / iocp是一种方法,而不是编写痛苦的select
或{{ 1}}基于apis。 epoll / kqueue / iocp不仅比基于WSAWaitForMultipleObjects
的替代方案更好,而且更容易编程。真。它们是更现代的apis,是基于更多经验而发明的。 (虽然它们不是跨平台,但即使选择也有可移植性问题......)。
前面提到的linux / bsd / windows的apis基于相同的概念,但在我看来,最简单和最容易学习的是linux的epoll api。它比select
调用更好,但是一旦你明白了,它就会更容易编程。如果你开始在Windows上使用IOCP而不是我看起来有点复杂。
如果您尚未使用这些api,那么如果您熟悉linux,那么肯定会给epoll一个机会,然后在Windows上实现相同的IOCP基于类似的概念和更复杂的重叠IO编程。使用IOCP,您将有理由使用select
,因为您无法在WSASend
的套接字上启动重叠IO,但您可以使用send
(或WSASend
)执行此操作。
编辑:如果您希望获得IOCP的最高性能,那么这里有一些额外的提示: