【问题标题】:C socket to handle full recvC 插座来处理完整的接收
【发布时间】:2018-06-10 22:49:54
【问题描述】:

Beej 的套接字编程指南/教程提供了一个易于使用的 sn-p,用于通过 send 发送所有数据。它被称为sendall,并在此处提供 - http://beej.us/guide/bgnet/html/single/bgnet.html#sendall

没有为recv all 提供这样的明确指导,尽管声明recv 也可以是部分的。为什么?

另外,我如何编写类似于sendall 建议的非阻塞recvall 函数。尽管没有简单的答案,但这似乎是常见问题解答。

【问题讨论】:

  • sendall() 知道它必须发送多少数据。由于普通 TCP 是一个字节/八位字节流协议,除非指定 TCP 之上的消息协议,否则不可能有这样的“recvall”功能。
  • @MartinJames - 谢谢,这很有帮助。
  • 你能解释一下接收全部并且也是非阻塞是什么意思吗?即,如果只有一半消息可用,行为应该是什么(根据 Martin James,接收者如何学习预期的消息长度?它是固定长度的吗?)
  • 我的想法是保持 MAXSIZE 的全局 char *buffer,并继续执行 recv 并将消息追加char *buffer,直到 recv 返回 0。
  • 你怎么会有一个非阻塞的 recvall?您想等待接收 100 个字节(例如),但您也不希望它等待?

标签: c sockets


【解决方案1】:

你原来的想法行不通。如果recv() 已经读取了所有发送的字节,它将阻塞,除非并且直到发送更多字节。如果没有发送过,你就被卡住了。正如上面的评论者所说,您需要某种方式来判断您何时到达传输结束。

有两种方法可以选择。最简单的方法是在发送完所有数据后关闭发送端的套接字。然后recv() 将在适当的时候返回 0 并且您知道您期望的所有数据都已到达。

另一种稍微困难的方法是在消息本身之前发送消息的长度。这很简单。在发送端(为简洁省略错误检查):

uint32_t msg_len = ...;
uint32_t network_byte_order_msg_len = htonl (msg_len);
int nbytes = sizeof (network_byte_order_msg_len);
sendall (skt, sizeof (uint32_t), &network_byte_order_msg_len, &nbytes);
nbytes = msglen;
sendall (skt, my_msg_buf, &nbytes);

在接收端,假设我们有一个函数recv_bytes,它在循环中调用recv,直到它得到它正在寻找的字节数:

uint32_t network_byte_order_msg_len;
int nbytes = sizeof (network_byte_order_msg_len);
recv_bytes (skt, &network_byte_order_msg_len, nbytes);
int msg_len = ntohl (&network_byte_order_msg_len);
void *msg_buf = malloc (msg_len);
nbytes = msg_len;
recv_bytes (skt, msg_buf, &nbytes);

请注意,通过这种方式,我们可以立即在接收器中分配正确大小的消息缓冲区,这既好又高效。

你可以写recv_bytes()吗?如果您愿意,可以将实现编辑到我的帖子中,以供未来的访问者使用。

编辑:该代码是 C++,我相信你可以修复它。

【讨论】:

    猜你喜欢
    • 2016-10-28
    • 1970-01-01
    • 2014-02-03
    • 1970-01-01
    • 1970-01-01
    • 2019-05-08
    • 2010-11-26
    • 2013-04-02
    • 1970-01-01
    相关资源
    最近更新 更多