循环时 recv() 函数如何工作?

Posted

技术标签:

【中文标题】循环时 recv() 函数如何工作?【英文标题】:How recv() function works when looping? 【发布时间】:2015-01-28 03:00:39 【问题描述】:

我在 MSDN 中阅读了有关 send() 和 recv() 函数的信息,但我不确定我是否理解一件事。

如果我发送一个大小为 256 的缓冲区,并接收前 5 个字节,那么下次我调用 recv() 函数时,它将指向第 6 个字节并从那里获取数据?

例如:

char buff[256];
memcpy(buff,"hello world",12);
send(sockfd, buffer, 100) //sending 100 bytes

//server side:
char buff[256];
recv(sockfd, buff, 5) // now buffer contains : "Hello"?
recv(socfd, buff,5) // now I ovveride the data and the buffer contains "World"?

谢谢!

【问题讨论】:

recv() 不会改变你的缓冲区指向的位置。但它会告诉你它读取了多少,这样你就可以从它停止的地方继续。不过,您需要自己调整传递它的指针和大小。 【参考方案1】:

在C中从TCP循环接收到缓冲区的正确方法如下:

char buffer[8192]; // or whatever you like, but best to keep it large
int count = 0;
int total = 0;

while ((count = recv(socket, &buffer[total], sizeof buffer - total, 0)) > 0)

    total += count;
    // At this point the buffer is valid from 0..total-1, if that's enough then process it and break, otherwise continue

if (count == -1)

    perror("recv");

else if (count == 0)

    // EOS on the socket: close it, exit the thread, etc.

【讨论】:

我知道这是旧的,但我认为应该是:while ((count = recv(socket, &buffer[total], sizeof (buffer) - total, 0)) > 0) 【参考方案2】:

您错过了主要细节 - 使用了什么样的套接字以及请求了什么协议。使用 TCP,数据是八位字节粒度的,是的,如果发送了 256 个字节并且您只读取了 5 个字节,其余 251 将在套接字缓冲区中等待(假设缓冲区更大,对于任何非嵌入式系统都是如此)并且您可以在下一个 recv() 上获取它们。使用 UDP 而没有 MSG_PEEK,单个数据报的其余部分会丢失,但是,如果指定了 MSG_PEEK,则下一个 recv() 将从一开始就给出数据报。使用 SCTP 或其他“顺序数据包”协议 AFAIK,得到与使用 UDP 相同的行为,但我不确定 Windows 实现细节。

【讨论】:

如果它不适合接收方的套接字接收缓冲区,它将在发送方的套接字发送缓冲区中,如果它不适合那里,则尚未发送。

以上是关于循环时 recv() 函数如何工作?的主要内容,如果未能解决你的问题,请参考以下文章

如何使发送和接收方法同时工作?

如何在 linux C 中解除对 recv() 或 recvfrm() 函数的阻塞

程序集分支/循环和函数如何工作

recv() 函数太慢

循环中的函数(返回另一个函数)如何工作? [复制]

在 for 循环中处理复杂的 send recv 消息