到目前为止,我所发现的关于使用套接字(recv
)接收数据的所有内容都是普通的旧版本。
即使它是C ++,它也要在std::vector<char>
(eww!)上逐字节地接收,或者defining a static size(例如vec.resize(BIG_NUMBER)
),然后接收。
但是,所有这些看起来都非常低效和/或丑陋,所以我想知道,在C ++中用最有效,最正确,更优雅的方式是什么? (不是C)
Web浏览器是一个很好的例子,说明某人需要接收未知数量的数据。 (为了示例而忽略Content-length
标题)
答案 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[]
)。