我正在使用c++
和TCP/IP
在sockets
编写分布式系统。
对于我的每条消息,我需要收到前5个字节才能知道传入消息的全长。
最好的方法是什么?
recv()
只有5个字节,然后再次recv()
。如果我选择这个,是否可以安全地假设我在recv中得到0或5个字节(也就是说不写循环继续尝试)?MSG_PEEK
recv()
一些较大的缓冲区大小,然后读取前5个字节,然后分配最终缓冲区。答案 0 :(得分:4)
你不需要知道任何事情。 TCP是一种流协议,在任何给定时刻,您都可以获得一个字节,或多达数兆字节的数据。使用TCP套接字的正确和唯一方法是循环读取。
char buf[4096]; // or whatever
std::deque<char> data;
for (int res ; ; )
{
res = recv(fd, buf, sizeof buf, MSG_DONTWAIT);
if (res == -1)
{
if (errno == EAGAIN || errno == EWOULDBLOCK)
{
break; // done reading
}
else
{
// error, break, die
}
}
if (res == 0)
{
// socket closed, finalise, break
}
else
{
data.insert(data.end(), buf, buf + res);
}
}
循环的唯一目的是将数据从套接字缓冲区传输到应用程序。如果队列中有足够的数据来尝试提取某种更高级别的应用程序消息,则您的应用程序必须单独决定 。
例如,在您的情况下,您将检查队列的大小是否至少为5,然后检查前五个字节,然后检查队列是否包含完整的应用程序消息。如果不是,则中止,如果是,则提取整个消息,如果从队列前面关闭则弹出。
答案 1 :(得分:1)
使用具有两种状态的状态机:
第一州。
在到达缓冲区时接收字节。当有5个或更多字节时,对前5个字节执行检查,并可能处理剩余的缓冲区。切换到第二个状态。
第二州。
在到达消息末尾时接收并处理字节。
答案 2 :(得分:0)
具体回答你的问题: