如何正确使用recv()sys调用

时间:2012-01-31 14:26:53

标签: c linux sockets network-programming tcpserver

我正在使用Linux下的Berkely SOCKET API编写TCP服务器。现在,客户端具有一组规范,客户端发送的每条消息都基于这些规范,即客户端发送的消息对应于规范指定的许多结构中的一个。现在的情况是服务器不知道客户端将在什么时间发送哪条消息。一旦我们收到消息,我们就可以弄清楚它是什么,但不是在此之前。客户端发送的消息长度可变,因此我们无法事先知道我们将获得什么消息。为了解决这个问题,我使用了以下方法:

const char *buf[4096] = { 0 };
          if ( recv (connected, buf, 4096, 0) == -1)
             {
               printf ("Error in recvng message\n");
               exit (-1);
             }

即我使用大小为4096的默认缓冲区(来自客户端的消息不能大于此大小)。在该缓冲区中接收然后我检查消息类型并采取相应的操作,如下所示:

struct ofp_header *oph;
oph=(struct ofp_header *)buf;
switch (oph->type)
{
case example_pkt:
handle_example_pkt();
break;
}

这很好但我只是想确认这是一个合适的方法还是还有其他可能比这更好的方法。所有人都非常感激。

感谢。

1 个答案:

答案 0 :(得分:5)

TCP是基于流的。这意味着如果您使用大于您的消息的缓冲区,您也可能会收到下一条消息的一部分。

这意味着您需要知道消息的大小,并将任何其他数据合并到下一条消息中。有两种明显的方法可以做到这一点:

  1. 修改协议,将每条消息的大小作为消息的前几个字节发送。首先读取大小,然后只读取那么多字节。

  2. 由于您知道每条消息的大小,因此请跟踪您读取的字节数。处理缓冲区中的第一条消息,然后从缓冲区中的剩余字节中减去该消息的大小。继续重复此过程,直到您要么A.没有剩余足够的字节来标识消息类型或B.没有足够的字节用于检测到的类型的消息。保存所有剩余字节并再次调用recv以读取更多数据。