[英]How to buffer data for send() and select()?
尽管send()在大多数时间都发送完所有数据后都成功了,但情况并非总是如此。 因此,建议人们对select()和poll()使用write-fdset来检查套接字何时可写。
通常的机制在保持可理解的源代码的同时,看起来如何实际上缓冲要发送的数据?
我对套接字编程的* nix方面并不十分熟悉,但是在Win32方面遇到了相同的问题。 缓冲并不是什么大问题(您将请求排入队列,并在写入完成后进行窥视以从队列中提交下一个),真正的问题是需要缓冲实际上正在处理流控制且无法解决流控制的信号仅使用缓冲:总是有一个消费者比生产者慢,并且缓冲基本上将失去控制。 您必须将流控制向上传播到生成数据的任何模块,这使接口变得非常复杂。 所有“写”请求必须支持指示流控制状态的返回码(即“停止写,没有更多空间!”)和回调,以邀请调用者恢复写操作。
因为我们在C ++领域,所以可以将数据存储在std :: vector中
新数据将附加到向量的末尾。 当您收到套接字可写的通知时,请尝试发送完整的向量。 send()将返回实际发送了多少。 然后只需从向量的开头擦除该字节数即可:
std::vector<char> buffer;
...
if( ! buffer.empty() )
{
int bytesRead = send( socket, &buffer[ 0 ], buffer.size(), flags );
if( bytesRead > 0 )
buffer.erase( 0, bytesRead );
else
// some error...
}
因此,可能还有更多错误检查要做,但是您明白了吗?
而不是对每个单独的发送请求进行排队,这样做的好处是,假设您正在使用TCP,则可以将多个更高级别的发送合并到一个套接字发送中。
但是正如Remus正确提到的那样,您的流控制和API有点棘手-即如何阻止缓冲区过大?
在编写需要以select()/ poll()循环为中心的OO时,您需要一个良好的抽象。 我一直发现自适应通信环境(ACE)Reactor类对此非常有用。 道格·施密特(Doug Schmidt)撰写了两本书《 C ++网络编程》,涵盖了这种环境,并且网络上还有其他各种内容,包括《 ACE Reactor的设计和使用》。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.