在C ++ / STL中使用recv最优雅的方式?

时间:2015-02-16 07:20:12

标签: c++ sockets stl

到目前为止,我所发现的关于使用套接字(recv)接收数据的所有内容都是普通的旧版本。

即使它是C ++,它也要在std::vector<char>(eww!)上逐字节地接收,或者defining a static size(例如vec.resize(BIG_NUMBER) ),然后接收。

但是,所有这些看起来都非常低效和/或丑陋,所以我想知道,在C ++中用最有效,最正确,更优雅的方式是什么? (不是C)

Web浏览器是一个很好的例子,说明某人需要接收未知数量的数据。 (为了示例而忽略Content-length标题)

3 个答案:

答案 0 :(得分:4)

我不知道任何STL方式,但无论如何,STL与它无关。 在处理旧的C API时,可以简单地用C ++类包装这些内容,使得外部开发人员看不到实现。

我建议编写包含SOCKET作为内部成员的Socket类,而不是创建一些包装C的方法(假设我们讨论流套接字!):

std::string Socket::receive (){
char buffer [SOME_SIZE];
int bytesRead;

std::string receivedData;

do{
    bytesRead = recv(socket,buffer,SOME_SIZE-2,0);
    buffer [SOME_SIZE-1] ='/0';
    receivedData += buffer;
} while (bytesRead != 0 && bytesRead != SOCKET_ERROR );

return receivedData;
}
顺便说一下,我怀疑你可能不完全理解recv(),recv()填写一个缓冲区,只要你反复调用recv()就会填写它。 套接字接收的字节数不限于缓冲区大小。 您可以使用此事实将数据附加到std :: string

答案 1 :(得分:2)

如果您不介意使用第三方库,Boost具有很好的模板来处理C ++中的套接字。看一下普通旧C套接字API函数和它们之间的equivalences;在this示例中,您将看到如何使用streambufs来避免为接收缓冲区分配内存。

答案 2 :(得分:0)

从根本上说,对于每个套接字,您需要有两个用户空间缓冲区:一个用于发送数据,另一个用于接收。

接收缓冲区的最佳大小与内核缓冲区大小相同。如果您的缓冲区较小 - 您的应用程序会执行更多recv次呼叫;如果更大 - 剩余容量可能永远不会被使用。

您使用的有线协议通常具有最大的邮件大小。你的缓冲区必须至少那么大。 Bandwidth-delay product可能还需要调整最小缓冲区大小。

通常,您希望将缓冲区与套接字一起分配一次,之后不要调整它们的大小。您可能希望将缓冲区存储为char[]std::array<char>std::vector<char>(但请避免new char[])。