在C套接字编程阻塞中是不是没有recv()?

时间:2013-06-07 18:33:47

标签: c sockets recv

在Receiver中,我有

recvfd=accept(sockfd,&other_side,&len);
while(1)
{
   recv(recvfd,buf,MAX_BYTES-1,0);
   buf[MAX_BYTES]='\0';
   printf("\n Number %d contents :%s\n",counter,buf);
   counter++;
}

在发件人中,我有

send(sockfd,mesg,(size_t)length,0);
send(sockfd,mesg,(size_t)length,0);
send(sockfd,mesg,(size_t)length,0);

MAX_BYTES是1024,mesg的长度是15.目前,它只调用recv一次。我想为每个相应的发送调用recv函数三次。我如何实现它?

5 个答案:

答案 0 :(得分:3)

要通过字节流协议发送离散消息,您必须将消息编码为某种框架语言。网络可以将协议划分为任意大小的数据包,因此接收不会以任何方式与您的消息相关联。接收器必须实现识别帧的状态机。

一个简单的成帧协议是有一些长度字段(比如两个八位字节:16位,最大帧长度为65535字节)。长度字段后面跟着那么多字节。

您甚至不能假设长度字段本身一次全部收到。您可能要求两个字节,但recv只能返回一个字节。从套接字收到的第一条消息不会发生这种情况,因为网络(或本地IPC管道)段永远不会只有一个字节长。但是在流中间的某个地方,16位长度字段的第一个字节可能会落在一个网络帧的最后位置。

处理此问题的一种简单方法是使用缓冲的I / O库而不是原始操作系统文件句柄。在POSIX环境中,您可以使用打开的套接字句柄,并使用fdopen函数将其与FILE *流关联。然后,您可以使用getcfread等函数来简化输入处理(稍微)。

如果无法接受带内成帧,则必须使用支持成帧的协议,即数据报类型套接字。这样做的主要缺点是IP上使用的基于主数据报的协议是UDP,而UDP是不可靠的。这会在您的应用程序中带来很多复杂性,以处理乱序和丢帧。帧的大小也受最大IP数据报大小的限制,大小约为64千字节,包括所有协议头。

大型UDP数据报会碎片化,如果网络中存在不可靠性,则会增加更大的不可靠性:如果丢失了任何IP片段,则整个数据包都会丢失。所有这些都必须重新传输;没有办法只重复丢失的片段。 TCP协议执行“路径MTU发现”以调整其段大小,以避免IP分段,并且TCP具有选择性重传以恢复丢失的段。

答案 1 :(得分:0)

我敢打赌你使用SOCK_STREAM创建了一个TCP套接字,这会导致在第一次recv调用期间将三条消息读入缓冲区。如果要逐个读取消息,请使用SOCK_DGRAM创建UPD套接字,或者开发某种类型的消息格式,以便在消息到达流时解析消息(假设消息的长度不一定是固定的) )。

答案 2 :(得分:0)

简而言之:,它正在阻止。但不是你想的那样。

recv()阻止,直到任何数据可读。但你事先并不知道它的大小。

在您的方案中,您可以执行以下操作:

  1. 调用select()并将要读取的套接字放入READ FD集
  2. select()返回正数时,您的套接字已准备好要读取数据
  3. 然后,检查您是否可以从套接字接收length个字节:
    recv(recvfd, buf, MAX_BYTES-1, MSG_PEEK)MSG_PEEK参见length或查看MSDN,他们也有{/ li>
  4. 现在您知道有多少数据可用
  5. 如果有length可用,则返回并且不执行任何操作
  6. 如果至少length可用,请阅读length并返回(如果有超过select(),我们将继续执行步骤2,因为新的READ事件将通过以下方式发出{{1}}

答案 3 :(得分:0)

首先以固定格式发送length,以length的大小(以字节为单位)传输此length,然后使recv()循环直到{已收到{1}}个字节。


注意事实(正如其他答案已经提到的那样),收到的块的大小和数量不一定需要与发送的相同。只接收的所有字节总和应与发送的所有字节总和相同。

阅读lengthrecv的手册页。特别是阅读有关这些功能 RETURN 的部分。

答案 4 :(得分:-3)

recv将阻塞,直到填满整个缓冲区,或者套接字关闭。

如果您想阅读length个字节并返回,那么您只能向recv传递一个大小为length的缓冲区。

您可以使用select来确定是否

  1. 有任何字节等待阅读,
  2. 等待读取多少字节,然后
  3. 只读那些字节
  4. 这可以避免recv阻止。

    修改

    重新阅读文档后,可能会出现以下情况:自length + length + length < MAX_BYTES - 1以来,您的三条“消息”可能会被一次性读取。

    如果永远不会返回recv,则另一种可能性是您可能需要flush来自发件人方的套接字。数据可能在缓冲区中等待实际发送到接收方。