首页 > 解决方案 > C 插座来处理完整的接收

问题描述

Beej 的 Socket 编程指南/教程提供了一个易于使用的片段,用于通过send. 它被调用sendall并在此处提供 - http://beej.us/guide/bgnet/html/single/bgnet.html#sendall

没有为recv所有人提供这样的明确指导,即使它也recv可能是部分的。为什么?

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

标签: csockets

解决方案


你原来的想法是行不通的。 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++,我相信你可以修复它。


推荐阅读